Skip to content

feat(letsplot): implement raincloud-basic#7710

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/raincloud-basic/letsplot
May 26, 2026
Merged

feat(letsplot): implement raincloud-basic#7710
MarkusNeusinger merged 6 commits into
mainfrom
implementation/raincloud-basic/letsplot

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: raincloud-basic - python/letsplot

Implements the python/letsplot version of raincloud-basic.

File: plots/raincloud-basic/implementations/python/letsplot.py

Parent Issue: #1876


🤖 impl-generate workflow

github-actions Bot added 2 commits May 26, 2026 23:11
Regen from quality 94. Addressed:
- canvas: switched from ggsize(1600,900)+scale=3 (4800x2700) to the
  canonical ggsize(800,450)+scale=4 (3200x1800) per Step 0 contract.
- palette: replaced custom hexes (#306998/#FFD43B/#5BA85B) with anyplot
  positions 1/2/3 (#009E73/#C475FD/#4467A3); Control is first series
  in brand green.
- theme-adaptive chrome: reads ANYPLOT_THEME, renders PAGE_BG #FAF8F1
  light / #1A1A17 dark, INK + INK_SOFT for text, RULE for grid, plus
  ELEVATED_BG for boxplot fill so it reads in both themes.
- outputs: now saves plot-{theme}.png and plot-{theme}.html instead of
  bare plot.png/plot.html.
- annotations: enlarged from size=10 to size=13 (prior weakness) and
  right-anchored at x=690 so labels stay inside the 200-700 panel.
- jitter density: reduced alpha 0.6 -> 0.5 and bumped size 3.5 -> 4.0
  to better resolve the dense Treatment B left cluster (prior weakness).

Preserved: horizontal raincloud metaphor (cloud above, box on baseline,
rain below), bimodal Treatment B distribution, two-annotation story.
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 26, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Warm off-white #FAF8F1 background. Title "raincloud-basic · python · letsplot · anyplot.ai" is bold dark ink at the top, fully visible above the plot area. Y-axis category labels (Control, Treatment A, Treatment B) are bold dark ink; x-axis "Reaction Time (ms)" and y-axis "Experimental Condition" titles are dark gray. Tick labels (200, 250, …, 700) are readable dark gray. Vertical major grid lines are subtle. Three half-violin clouds rise above each baseline in canonical anyplot colors — Control = brand green #009E73, Treatment A = lavender #C475FD, Treatment B = blue #4467A3. Boxplots with near-white ELEVATED_BG fill sit centered on each baseline with median + quartile markers. Jittered rain points (color-matched, alpha ~0.5) fall below each baseline. Italic-gray annotations with thin arrows highlight Treatment A's faster mean and Treatment B's bimodal cluster. All text is clearly readable against the light background.

Dark render (plot-dark.png): Warm near-black #1A1A17 background. The same title and axis labels render in light ink #F0EFE8 and are fully readable; tick labels render in light INK_SOFT gray and are legible. Vertical grid lines are subtle light rule lines. Data colors are identical to the light render (green / lavender / blue — only chrome flipped). Box fills switch to the dark ELEVATED_BG #242420 with light box outlines — boxes still read cleanly. Italic annotations and arrows switch to light ink — no dark-on-dark failures detected. Brand green is visible on both surfaces as expected.

Score: 89/100

Category Score Max
Visual Quality 28 30
Design Excellence 14 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 9 10
Total 89 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All text readable in both themes; sizes explicitly set
  • VQ-02: No Overlap (5/6) — Annotation arrows terminate inside violin curves (3 arrows clip into clouds)
  • VQ-03: Element Visibility (6/6) — Rain alpha=0.5, size=4 works for ~80 points/category
  • VQ-04: Color Accessibility (2/2) — CVD-safe trio
  • VQ-05: Layout & Canvas (4/4) — Exact 3200x1800, canvas gate passed
  • VQ-06: Axis Labels & Title (2/2) — "Reaction Time (ms)" with units
  • VQ-07: Palette Compliance (2/2) — First series #009E73; canonical order; theme-correct chrome on both renders

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (5/8) — Polished composition; arrow routing detracts slightly
  • DE-02: Visual Refinement (4/6) — Y-axis line + ticks removed, subtle grid; could remove x-axis line too
  • DE-03: Data Storytelling (5/6) — Annotations surface bimodality and speed advantage — strong insight delivery

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct raincloud (violin + box + jitter)
  • SC-02: Required Features (4/4) — Half-violin via show_half=1, moderate jitter, alpha on rain, median + quartiles
  • SC-03: Data Mapping (3/3) — Categories on y-axis; cloud-up / box-center / rain-down metaphor via position_nudge
  • SC-04: Title & Legend (3/3) — Title exact; legend hidden (redundant with y-axis encoding)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Treatment B's bimodal data showcases the raincloud's distinctive value
  • DQ-02: Realistic Context (5/5) — Reaction-time experiment, neutral framing
  • DQ-03: Appropriate Scale (4/4) — 250-650 ms is plausible

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — No functions/classes
  • CQ-02: Reproducibility (2/2) — np.random.seed(42)
  • CQ-03: Clean Imports (2/2) — Explicit named imports, all used
  • CQ-04: Code Elegance (2/2) — No fake UI, appropriate complexity
  • CQ-05: Output & API (1/1) — plot-{THEME}.png + .html via ggsave

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — ggplot grammar, scale_*_manual, scale_y_discrete with limits, themed element_* tokens
  • LM-02: Distinctive Features (4/5) — show_half=1 (half-violin), position_nudge (layer offsets), ggsave HTML export — distinctly lets-plot

Score Caps Applied

  • None

Strengths

  • Correct raincloud anatomy: half-violin clouds nudged above each baseline (show_half=1), boxplot centered on the baseline, jittered rain below — the spec's vertical metaphor (cloud up, rain down) is preserved cleanly for all three conditions.
  • Idiomatic lets-plot composition: ggplot grammar with layered geom_violin / geom_boxplot / geom_jitter, position_nudge to offset each layer, scale_y_discrete with explicit limits to control category order.
  • Theme-adaptive chrome wired through tokens (PAGE_BG, ELEVATED_BG, INK, INK_SOFT, RULE) so both light (#FAF8F1) and dark (#1A1A17) renders are fully legible — no dark-on-dark or light-on-light failures.
  • Canonical anyplot palette in canonical order: Control = #009E73 (brand green, first series as required), Treatment A = #C475FD, Treatment B = #4467A3.
  • Strong data storytelling: italic-gray annotations with arrows highlight the bimodal Treatment B distribution and Treatment A's ~70ms speed advantage.
  • Canvas exact at 3200×1800 (ggsize(800,450) + scale=4); canvas gate not triggered.

Weaknesses

  • The two annotation arrows for "Two distinct response clusters" both terminate inside the Treatment B violin curve — the arrowheads overlap the cloud fill. Route the arrows so the heads land just outside the violin silhouette, or shorten the segments so they stop at the cluster centers without crossing the boundary.
  • The annotation arrow for "~70ms faster mean than Control" crosses through the upper portion of the Treatment A violin curve. Adjust start/end so the segment skirts the violin shape.
  • DE-02 could push further: the x-axis line (axis_line_x) competes mildly with the vertical grid. Consider removing it (theme_minimal-style) since the grid already anchors the x-scale.

Issues Found

  1. VQ-02 MINOR: Three annotation arrows terminate inside violin fills (Treatment A x1, Treatment B x2)
    • Fix: Adjust arrow start/end coordinates so heads land just outside violin silhouettes, or stop arrows at cluster centers.
  2. DE-02 LOW: Visible axis_line_x is slightly redundant with the vertical grid
    • Fix: Replace axis_line_x=element_line(...) with axis_line_x=element_blank() for a cleaner minimal look.

AI Feedback for Next Attempt

Strong, ship-ready raincloud. To push the score higher: clean up annotation-arrow routing so arrowheads do not pierce the violin fills (they currently terminate inside the Treatment A and Treatment B clouds), and consider removing the x-axis line for an even more minimal look. Everything else — palette, theme tokens, spec metaphor, canvas size, code structure — is on point.

Verdict: APPROVED

@github-actions github-actions Bot added quality:89 Quality score 89/100 ai-rejected Quality not OK, triggers update labels May 26, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels May 26, 2026
Attempt 1/3 - fixes based on AI review

- Reroute annotation arrows so arrowheads land just above each violin's
  top edge instead of piercing the cloud fill (VQ-02).
- Remove axis_line_x (theme_minimal-style) since the vertical grid
  already anchors the x-scale (DE-02).
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 26, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white #FAF8F1 background — matches the anyplot light surface, not pure white. Title "raincloud-basic · python · letsplot · anyplot.ai" renders in bold dark ink at the top, fully visible. Y-axis category labels (Control, Treatment A, Treatment B) are bold dark ink; x-axis title "Reaction Time (ms)" and y-axis title "Experimental Condition" are dark gray; x-tick labels (200, 250, …, 700) are dark gray and legible. Subtle vertical major grid lines anchor the x-scale; axis lines and ticks are blanked. Three half-violin clouds rise above each category baseline in canonical anyplot colors — Control = #009E73 brand green, Treatment A = #C475FD lavender, Treatment B = #4467A3 blue. Boxplots with light/cream ELEVATED_BG fill sit on each baseline with median + quartile markers. Color-matched jittered rain points (alpha ~0.5) fall below each baseline. Italic-gray annotations with thin arrows highlight Treatment A's faster mean and Treatment B's two response clusters. All text is clearly readable — no light-on-light failures.

Dark render (plot-dark.png): Warm near-black #1A1A17 background — matches the anyplot dark surface, not pure black. Title and axis titles render in light INK (#F0EFE8) and are fully readable; tick labels render in light INK_SOFT gray and stay legible. Vertical grid lines are subtle light rule lines. Data colors are identical to the light render — only chrome flipped (Control green, Treatment A lavender, Treatment B blue). Italic annotation text and arrow segments switch to light ink — no dark-on-dark text failures. Brand green reads cleanly on both surfaces. One minor observation: the boxplot interior fills in the dark render look lighter than the intended ELEVATED_BG (#242420) token would suggest — visually striking and high-contrast, but worth verifying the explicit geom_boxplot(fill=ELEVATED_BG, ...) override is winning over the aes(fill='condition') mapping. Every text element passes the dark-readability check.

Score: 94/100

Category Score Max
Visual Quality 29 30
Design Excellence 16 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 9 10
Total 94 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — All text readable in both themes; sizes explicitly set via theme().
  • VQ-02: No Overlap (6/6) — Arrow tips now resolve outside violin silhouettes; attempt-1 piercing addressed.
  • VQ-03: Element Visibility (6/6) — Jitter alpha=0.5 + size=4 reads well for ~80 points/category; violins at alpha=0.7 clear.
  • VQ-04: Color Accessibility (2/2) — Green / lavender / blue trio is CVD-safe.
  • VQ-05: Layout & Canvas (4/4) — Exact 3200×1800; canvas gate not triggered; no overflow.
  • VQ-06: Axis Labels & Title (2/2) — "Reaction Time (ms)" with units, "Experimental Condition" descriptive.
  • VQ-07: Palette Compliance (2/2) — First series #009E73; canonical anyplot order; theme-correct chrome on both renders.

Design Excellence (16/20)

  • DE-01: Aesthetic Sophistication (6/8) — Polished, tokenized chrome with custom palette. Title at plot_title size=16 fills ~30–35% of plot width; could push closer to the 50–70% sweet spot.
  • DE-02: Visual Refinement (5/6) — Spines/ticks blanked, vertical-only subtle grid, x-axis line removed per attempt-1 feedback. Dark-mode boxplot interior appears lighter than the intended ELEVATED_BG token would suggest.
  • DE-03: Data Storytelling (5/6) — Strong annotations surface bimodality + speed advantage. The two "Two distinct response clusters" arrows land in the rain area rather than at the cloud peaks themselves.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct raincloud (half-violin + box + jitter).
  • SC-02: Required Features (4/4) — show_half=1, moderate jitter (height=0.05), alpha=0.5 on rain, median + quartiles in boxplot.
  • SC-03: Data Mapping (3/3) — Horizontal; categories on y-axis, values on x-axis; cloud-up / box-on-line / rain-down via position_nudge.
  • SC-04: Title & Legend (3/3) — Title exactly the required slug; legend hidden (redundant with y-axis encoding).

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Treatment B's intentional bimodal mixture showcases the raincloud's distinctive value.
  • DQ-02: Realistic Context (5/5) — Reaction-time experiment; neutral framing.
  • DQ-03: Appropriate Scale (4/4) — ~250–650 ms is plausible for human reaction times.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42).
  • CQ-03: Clean Imports (2/2) — Explicit named imports, all used.
  • CQ-04: Code Elegance (2/2) — No fake UI; appropriate complexity.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png + .html via ggsave.

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Layered geoms via grammar, position_nudge, scale_*_manual, scale_y_discrete(limits=...), tokenized element_* theme.
  • LM-02: Distinctive Features (4/5) — show_half=1, position_nudge raincloud offset trick, ggsave HTML export. Could lean further into lets-plot interactivity (e.g. tooltips) for the bonus point.

Score Caps Applied

  • None

Strengths

  • Correct raincloud anatomy: half-violin cloud above each baseline (show_half=1), boxplot centered on the baseline, jittered rain below — the spec's vertical metaphor is preserved cleanly for all three conditions.
  • Idiomatic lets-plot composition: layered geom_violin / geom_boxplot / geom_jitter combined via position_nudge, scale_y_discrete with explicit limits to control category order.
  • Theme-adaptive chrome wired through tokens (PAGE_BG, ELEVATED_BG, INK, INK_SOFT, RULE) so both #FAF8F1 light and #1A1A17 dark renders pass readability checks.
  • Canonical anyplot palette in canonical order: Control = #009E73, Treatment A = #C475FD, Treatment B = #4467A3; data colors identical across themes.
  • Strong data storytelling: italic-gray annotations surface Treatment A's faster mean and Treatment B's bimodal cluster — exactly the kind of insight a raincloud is designed to reveal.
  • Attempt-1 fixes landed: arrowheads no longer pierce violin fills; axis_line_x removed for the cleaner minimal look called out in DE-02.
  • Canvas exact at 3200×1800; canvas gate not triggered. Reproducible seed; no functions/classes; only-used imports.

Weaknesses

  • DE-01 (Title proportion): Title at plot_title size=16 fills only ~30–35% of the wide landscape canvas — could push a couple of points larger (e.g. size=18) to land closer to the 50–70% sweet spot without overflowing.
  • DE-02 (Dark-mode box fill): Boxplot interiors in the dark render appear noticeably lighter than the intended dark ELEVATED_BG (#242420) — they read closer to cream/light-gray. Worth verifying the explicit geom_boxplot(fill=ELEVATED_BG, ...) override is winning over the aes(fill='condition') mapping with alpha=0.95; dropping the fill aesthetic specifically on the boxplot layer (or passing fill=None in aes for that geom) would lock the box interior to the elevated dark token.
  • DE-03 (Bimodal arrow target): The two "Two distinct response clusters" arrows currently land in the rain area below the Treatment B baseline rather than at the bimodal cloud peaks. Nudging the segment endpoints up to land just outside the top edge of each violin peak would make the bimodality call-out unambiguous.

Issues Found

  1. DE-01 LOW: Title underfills the wide canvas at size=16.
    • Fix: Bump plot_title=element_text(size=18, face='bold', color=INK) so the title lands ~50–60% of plot width.
  2. DE-02 LOW: Dark-mode boxplot interior renders lighter than the intended ELEVATED_BG token.
    • Fix: Move fill="condition" off the top-level aes() and add aes(fill='condition') only to geom_violin, so geom_boxplot(fill=ELEVATED_BG, ...) cleanly owns its fill without the categorical mapping leaking through.
  3. DE-03 LOW: Bimodal annotation arrows terminate in the rain area, not at the violin peaks.
    • Fix: Adjust geom_segment yend for the two bimodal arrows to land just outside the top of each Treatment B violin peak (e.g. ~yend=1.18 to sit just above the cloud's top edge with the current position_nudge(y=0.12)).

AI Feedback for Next Attempt

Very close to ship-ready. To close the remaining gap: (1) bump plot_title size from 16 to ~18 so the long mandated title fills more of the wide canvas; (2) verify the dark-mode boxplot fill is actually picking up ELEVATED_BG (#242420) — the box interiors look lighter than expected in dark, which suggests the aes(fill='condition') mapping may be leaking past the explicit geom_boxplot(fill=...) override; (3) reroute the two "Two distinct response clusters" arrowheads so they land just above the Treatment B violin peaks rather than in the rain area below the baseline. Everything structural — palette, theme tokens, raincloud metaphor, canvas size, reproducibility — is on point.

Verdict: APPROVED

@github-actions github-actions Bot added quality:94 Quality score 94/100 ai-approved Quality OK, ready for merge and removed quality:89 Quality score 89/100 labels May 26, 2026
@MarkusNeusinger MarkusNeusinger merged commit 29510de into main May 26, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/raincloud-basic/letsplot branch May 26, 2026 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt quality:94 Quality score 94/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant