Skip to content

feat(matplotlib): implement lollipop-basic#5441

Merged
github-actions[bot] merged 5 commits intomainfrom
implementation/lollipop-basic/matplotlib
Apr 26, 2026
Merged

feat(matplotlib): implement lollipop-basic#5441
github-actions[bot] merged 5 commits intomainfrom
implementation/lollipop-basic/matplotlib

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: lollipop-basic - python/matplotlib

Implements the python/matplotlib version of lollipop-basic.

File: plots/lollipop-basic/implementations/python/matplotlib.py

Parent Issue: #934


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 26, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white background (#FAF8F1), consistent with the anyplot.ai light surface. Title reads "lollipop-basic · matplotlib · anyplot.ai" in dark ink — clearly readable. X-axis label "Product Category" and Y-axis label "Sales (thousands)" are in dark, legible text. Category tick labels are rotated 45° in dark gray, all readable without collision. Ten categories are displayed from Electronics (87k) to Office Supplies (25k) in descending order. Both stems (vlines) and circular dots (scatter) appear in brand green (#009E73). Subtle horizontal grid lines are present. All text is readable against the light background.

Dark render (plot-dark.png): The plot renders on a warm near-black background (#1A1A17). Title, axis labels, and tick labels appear in light text against the dark surface — no dark-on-dark failures observed. The data colors (stems and dots) are identical to the light render — the same brand green (#009E73) throughout. Subtle horizontal grid lines remain visible. All text is readable against the dark background.

⚠️ Critical discrepancy: The rendered images show correct anyplot.ai styling (brand green #009E73, proper backgrounds, "anyplot.ai" branding), but the source code in implementations/python/matplotlib.py uses #306998 (blue) for stems, #FFD43B (yellow) for dots, has the title hardcoded as "lollipop-basic · matplotlib · pyplots.ai", and saves to "plot.png" instead of f"plot-{THEME}.png". The images cannot have been generated from the current source code. This is a critical code-image mismatch.

Score: 84/100

Category Score Max
Visual Quality 28 30
Design Excellence 12 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 8 10
Library Mastery 6 10
Total 84 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All text readable at correct sizes in both themes; tick label colors not explicitly wired through INK_SOFT token in source
  • VQ-02: No Overlap (6/6) — No collisions; rotated tick labels all legible
  • VQ-03: Element Visibility (6/6) — Stems and dots clearly visible in both renders at proper sizes
  • VQ-04: Color Accessibility (2/2) — Single high-contrast color; accessible
  • VQ-05: Layout & Canvas (4/4) — Good 16:9 proportions, nothing cut off
  • VQ-06: Axis Labels & Title (2/2) — Descriptive with units; correct title format in renders
  • VQ-07: Palette Compliance (1/2) — Images show brand green but source uses #306998/#FFD43B (non-Okabe-Ito); code-image mismatch penalized

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Clean, consistent single-color design; above default for minimalist clarity and brand cohesion
  • DE-02: Visual Refinement (3/6) — Spines removed in renders; grid present but uses dashed style (--) at alpha=0.3, slightly above style guide opacity range
  • DE-03: Data Storytelling (4/6) — Descending sort creates clear ranking visualization; lollipop reduces visual clutter vs bars

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct vertical lollipop: vlines stems + scatter circular dots
  • SC-02: Required Features (4/4) — Stems from baseline, circular markers, vertical orientation, sorted by value — all present
  • SC-03: Data Mapping (3/3) — Categories on x-axis, values on y-axis, all 10 categories displayed
  • SC-04: Title & Legend (3/3) — Rendered title shows correct format; no legend appropriate for single series

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — All lollipop features demonstrated with 10 categories (within 5–20 range)
  • DQ-02: Realistic Context (5/5) — Product sales by category; realistic and neutral
  • DQ-03: Appropriate Scale (4/4) — Values 25–87 (thousands) plausible; y-axis starts at 0 correctly

Code Quality (8/10)

  • CQ-01: KISS Structure (3/3) — No functions or classes; clean linear code
  • CQ-02: Reproducibility (2/2) — Hardcoded data is deterministic
  • CQ-03: Clean Imports (2/2) — Only matplotlib.pyplot and numpy; both used
  • CQ-04: Code Elegance (1/2) — No fake UI, but wrong palette colors and missing ANYPLOT_THEME handling
  • CQ-05: Output & API (0/1) — Saves to "plot.png" instead of f"plot-{THEME}.png"; pipeline cannot find expected output files

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — ax.vlines for stems is the natural matplotlib primitive; Axes methods used throughout
  • LM-02: Distinctive Features (2/5) — vlines is a good matplotlib-specific choice; no other library-distinctive features

Score Caps Applied

  • None

Strengths

  • Clean, minimal code structure with no functions or classes — easy to read and maintain
  • Correct chart type: vertical lollipop with ax.vlines stems and ax.scatter circular dots
  • Sorted data descending creates clear ranking visualization with good data storytelling
  • Proper font sizes for 4800×2700 canvas (title 24pt, axis labels 20pt, tick labels 16pt)
  • Idiomatic matplotlib API usage: Axes methods, vlines is the natural primitive for lollipop stems

Weaknesses

  • CRITICAL: No ANYPLOT_THEME handling — no os.getenv("ANYPLOT_THEME") logic; background, text, and grid colors are all matplotlib defaults; both renders would look identical without theme adaptation
  • CRITICAL: Wrong output filename — saves to "plot.png" instead of f"plot-{THEME}.png"; pipeline expects plot-light.png and plot-dark.png
  • CRITICAL: Wrong palette — stems use #306998 (non-Okabe-Ito blue) and dots use #FFD43B (non-Okabe-Ito yellow); single-series should use #009E73 (brand green) for both
  • CRITICAL: Wrong branding in title — uses "pyplots.ai" instead of "anyplot.ai"
  • Top/right spines not removed — no ax.spines['top'].set_visible(False) or ax.spines['right'].set_visible(False) in source
  • Grid uses dashed linestyle (--) and alpha=0.3 — style guide specifies solid lines at 10–15% opacity

Issues Found

  1. CQ-05 FAIL: Saves to "plot.png" — must be plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches='tight', facecolor=PAGE_BG)
  2. VQ-07 / CQ-04 FAIL: Missing ANYPLOT_THEME block — add import os, define THEME = os.getenv("ANYPLOT_THEME", "light"), then set PAGE_BG, INK, INK_SOFT tokens; pass facecolor=PAGE_BG to fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG) and ax.set_facecolor(PAGE_BG); wire all text/tick/spine colors through those tokens
  3. VQ-07 FAIL: Replace color="#306998" with color="#009E73" for stems and color="#009E73" for dots (single-series Okabe-Ito rule); remove the two-tone design
  4. SC-04 FAIL: Change title to "lollipop-basic · matplotlib · anyplot.ai"
  5. DE-02: Remove top/right spines: ax.spines['top'].set_visible(False); ax.spines['right'].set_visible(False); change grid to solid lines at alpha=0.15

AI Feedback for Next Attempt

Complete rewrite of the save/theme block is required. Add import os, set THEME = os.getenv("ANYPLOT_THEME", "light"), define the full token set (PAGE_BG, ELEVATED_BG, INK, INK_SOFT), apply them to figure background, title, axis labels, tick params, and spines. Change all data colors to #009E73 (single series = brand green only). Save as f"plot-{THEME}.png" with facecolor=PAGE_BG. Fix branding to "anyplot.ai". Remove top/right spines. Use subtle solid grid at alpha=0.15.

Verdict: REJECTED

@github-actions github-actions Bot added quality:84 Quality score 84/100 ai-rejected Quality not OK, triggers update labels Apr 26, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Apr 26, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/3

Applied fixes based on AI review feedback.

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


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 26, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white (#FAF8F1) background — correct for the anyplot.ai light surface. The title "lollipop-basic · matplotlib · anyplot.ai" appears in dark ink at 24pt, clearly readable. Y-axis label "Sales (thousands)" and X-axis label "Product Category" are visible at 20pt in dark ink. Category tick labels are rotated 45° in dark gray (INK_SOFT), all readable without overlap. Subtle horizontal y-axis grid lines (solid, alpha=0.15) are present but not dominant. Top and right spines are removed; left and bottom spines are in dark gray. Data is rendered in brand green (#009E73): thin vertical stems (linewidth=2.5) from the baseline to circular markers (s=300 with PAGE_BG edge for visual definition), for all 10 categories sorted descending from Electronics (87K) to Office Supplies (25K). All text is clearly readable against the light background — no light-on-light failures.

Dark render (plot-dark.png): The plot renders on a warm near-black (#1A1A17) background — correct for the anyplot.ai dark surface. The title appears in light off-white (#F0EFE8) at 24pt, clearly readable. Axis labels are visible in the same light off-white token. Category tick labels appear in light gray (#B8B7B0 INK_SOFT) at 16pt — readable against the dark background with no dark-on-dark failures. Grid lines appear in a light color (alpha=0.15), subtle but visible. Left and bottom spines are in light gray. Data colors are identical to the light render — brand green (#009E73) stems and markers; only chrome elements flipped between themes. All text is clearly readable against the dark background.

Both paragraphs are required. A review that only describes one render is invalid.

Score: 88/100

Category Score Max
Visual Quality 30 30
Design Excellence 12 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 6 10
Total 88 100

Visual Quality (30/30)

  • VQ-01: Text Legibility (8/8) — All font sizes explicitly set: title 24pt, axis labels 20pt, tick labels 16pt. Both renders fully readable.
  • VQ-02: No Overlap (6/6) — Category labels rotated 45° with ha=right, no overlapping elements in either render.
  • VQ-03: Element Visibility (6/6) — Stems at linewidth=2.5 and markers at s=300 with PAGE_BG edge — optimal sizing for 10 data points.
  • VQ-04: Color Accessibility (2/2) — Single color (#009E73) throughout, high contrast against both backgrounds.
  • VQ-05: Layout & Canvas (4/4) — 16:9 canvas, tight_layout applied, nothing cut off, balanced margins.
  • VQ-06: Axis Labels & Title (2/2) — "Sales (thousands)" with units; "Product Category" descriptive.
  • VQ-07: Palette Compliance (2/2) — Single series uses #009E73 (brand green). Light bg=#FAF8F1, dark bg=#1A1A17. INK/INK_SOFT tokens applied to all chrome. Both renders theme-correct.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Clean single-color minimalist design above default (4). PAGE_BG edge on markers adds subtle definition. Sorted data improves readability. No emphasis techniques or visual hierarchy beyond the baseline to elevate further.
  • DE-02: Visual Refinement (4/6) — Top/right spines removed; y-axis-only solid grid at alpha=0.15; set_axisbelow ensures grid stays behind data. Noticeably above default.
  • DE-03: Data Storytelling (3/6) — Descending sort creates a clear ranking story. No value labels, no emphasis on extremes, no focal point. Above default (2) due to sorted presentation.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct vertical lollipop with ax.vlines stems and ax.scatter circular markers.
  • SC-02: Required Features (4/4) — Stems from baseline (ymin=0), circular markers, vertical orientation, data sorted by value — all spec requirements met.
  • SC-03: Data Mapping (3/3) — Categories on x-axis, values on y-axis, all 10 categories displayed, y-axis starts at 0.
  • SC-04: Title & Legend (3/3) — Title exactly "lollipop-basic · matplotlib · anyplot.ai". No legend (correct for single series).

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — All lollipop features shown: baseline start, stems, circular markers, sorted order, 10 categories within the 5-20 spec range.
  • DQ-02: Realistic Context (5/5) — Product sales by retail category — realistic, neutral business scenario.
  • DQ-03: Appropriate Scale (4/4) — Values 25–87 (thousands) plausible for retail category sales; good spread.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat structure: theme tokens → data → plot → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — Hardcoded data is fully deterministic.
  • CQ-03: Clean Imports (2/2) — os, matplotlib.pyplot, numpy — all imported are used.
  • CQ-04: Code Elegance (2/2) — Clean Pythonic code, appropriate complexity, no fake UI elements.
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png using current matplotlib API.

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — ax.vlines() is the natural matplotlib primitive for lollipop stems. ax.scatter(), set_axisbelow(), Axes methods throughout — idiomatic.
  • LM-02: Distinctive Features (2/5) — ax.vlines() and set_axisbelow() are good matplotlib-specific choices, but no other library-distinctive features leveraged.

Score Caps Applied

  • None

Strengths

  • All critical issues from attempt 1 fully resolved: ANYPLOT_THEME handling, correct output filename (plot-{THEME}.png), brand green palette (#009E73), correct anyplot.ai branding
  • Clean code structure: flat imports→data→plot→save with no functions or classes
  • Correct lollipop chart type using ax.vlines() for stems (idiomatic matplotlib primitive) and ax.scatter() for circular markers
  • Fully theme-adaptive chrome: INK and INK_SOFT tokens applied to title, axis labels, tick labels, spines, and grid — both renders pass legibility check
  • Data sorted descending creates immediate ranking story; 10 categories within spec-recommended 5-20 range
  • Appropriate element sizing: stems at linewidth=2.5, markers at s=300 with PAGE_BG edge for visual definition

Weaknesses

  • DE-01 (5/8): Single-color treatment with no visual emphasis on notable data points (e.g., top performer Electronics or lowest Office Supplies); no value labels on markers forcing readers to read the y-axis for exact values
  • DE-03 (3/6): Sorted order aids ranking but no additional storytelling — no focal point, no annotation, no color variation to guide the viewer's eye to the key insight
  • LM-02 (2/5): Uses ax.vlines() and set_axisbelow() which are good library-specific choices, but no other distinctive matplotlib features leveraged

Issues Found

  1. DE-01 MEDIUM: Clean but no visual emphasis — single brand green for all 10 bars, no differentiation
    • Fix: Add value labels (ax.text) directly on or above each marker for immediate data readability; OR highlight top/bottom performers with a slightly different marker style or annotation
  2. DE-03 MEDIUM: No focal point or storytelling beyond sorted order
    • Fix: Use a subtle color contrast (e.g., top 3 bars in full #009E73, remaining in a lighter alpha) to guide the viewer's attention to the key insight, or add a single annotation highlighting the leader

AI Feedback for Next Attempt

The implementation is technically excellent — all critical issues are fixed and both renders pass. To reach 90+, improve Design Excellence (currently 12/20). Specifically: (1) Add direct value labels on or near each marker using ax.text() so readers see exact values without needing the y-axis; (2) Create a visual focal point — for example, use full opacity for the top performer and 0.5 alpha for the rest, or add a single callout annotation for "Electronics" as the clear leader; (3) These changes can bring DE-01 to 6+ and DE-03 to 4+, pushing the total above 90.

Verdict: REJECTED

@github-actions github-actions Bot added quality:88 Quality score: 88/100 ai-approved Quality OK, ready for merge labels Apr 26, 2026
@github-actions github-actions Bot merged commit 986dc64 into main Apr 26, 2026
3 checks passed
@github-actions github-actions Bot deleted the implementation/lollipop-basic/matplotlib branch April 26, 2026 12:50
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:84 Quality score 84/100 quality:88 Quality score: 88/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants