Skip to content

feat(matplotlib): implement lollipop-basic#9595

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/lollipop-basic/matplotlib
Jul 1, 2026
Merged

feat(matplotlib): implement lollipop-basic#9595
MarkusNeusinger merged 6 commits into
mainfrom
implementation/lollipop-basic/matplotlib

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 1, 2026

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

github-actions Bot added 2 commits July 1, 2026 05:51
Regen from quality 88. Addressed:
- Canvas: corrected figsize=(8,4.5) dpi=400, removed bbox_inches="tight"
- Font sizes: title 12pt, axis labels 10pt, tick labels 8pt (per library guide)
- DE-01: added value labels (e.g. "87K") above each lollipop marker
- DE-03: added average reference line (axhline) + top performer callout annotation
- LM-02: leveraged ax.annotate() with arrowprops, ax.axhline(), mticker.FuncFormatter
@claude

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Warm off-white (#FAF8F1) background. Title "lollipop-basic · matplotlib · anyplot.ai" is rendered in dark ink at the top — readable. Y-axis label "Sales (thousands)" in dark text, left side — readable and includes units. Ten brand-green (#009E73) lollipops are cleanly rendered: thin stems via vlines, circular markers via scatter, sorted descending from Electronics (87K) to Office Supplies (25K). Small value labels (fontsize=6.5) above each marker show numeric values; these are legible at full resolution but borderline on mobile scale. A dashed average reference line at 52K spans the plot with a small "avg 52K" annotation (fontsize=6) — very small. A "Top performer" callout annotation box (fontsize=6.5) with arrow points to the Electronics dot. Top/right spines removed; subtle horizontal y-axis grid (alpha=0.15). X-axis tick labels are rotated 45° and readable. The x-axis label "Product Category" appears very close to the bottom canvas edge, with the bottom pixels of the descenders appearing cut off. Legibility verdict: PASS for main elements; the avg/value label sizes are very small on mobile, and x-axis label is at the canvas bottom edge.

Dark render (plot-dark.png): Warm near-black (#1A1A17) background. Title appears in near-white (#F0EFE8) — readable. Y-axis label in near-white — readable. Same ten brand-green (#009E73) lollipops — data colors are identical to the light render (only chrome flips). Tick labels render in secondary ink (#B8B7B0) — readable against the dark background. The "Top performer" annotation box uses ELEVATED_BG (#242420) with light text (INK=#F0EFE8) — correctly theme-adapted. The dashed average line uses INK_MUTED (#A8A79F) — subtle but visible. Grid lines use INK (#F0EFE8) at alpha=0.15 — appropriately subtle. No dark-on-dark text failures detected. X-axis label "Product Category" shows the same bottom-edge proximity concern as the light render. Legibility verdict: PASS for main chrome elements; same small-font concern applies; avg label "avg 52K" is very small at fontsize=6.

Score: 85/100

Category Score Max
Visual Quality 26 30
Design Excellence 13 20
Spec Compliance 14 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 85 100

Visual Quality (26/30)

  • VQ-01: Text Legibility (6/8) — Title, axis labels, tick labels all explicitly sized and readable at desktop resolution. Value labels (fontsize=6.5) and avg reference label (fontsize=6) are too small for mobile-scaled view (~400 px wide). Reduce annotation/value text loss by bumping value labels to ≥8pt and avg label to ≥7.5pt.
  • VQ-02: No Overlap (6/6) — No overlapping text or data elements in either render.
  • VQ-03: Element Visibility (5/6) — Lollipop stems and markers are clearly visible. Differential marker sizing (s=120 for top vs s=80 for rest) adds emphasis. Minor: markers could be slightly larger overall for this 10-point dataset (s=100 / s=140 would pop more at mobile scale).
  • VQ-04: Color Accessibility (2/2) — Single-series brand green with good contrast on both surfaces; CVD-safe.
  • VQ-05: Layout & Canvas (3/4) — Proportions are generally good. Minor concern: the x-axis label "Product Category" appears at the very bottom canvas edge with its descenders appearing clipped. Increase from 0.22 → 0.26 to give the xlabel clear breathing room.
  • VQ-06: Axis Labels & Title (2/2) — "Product Category" and "Sales (thousands)" — descriptive with units.
  • VQ-07: Palette Compliance (2/2) — First (and only) series is #009E73. Light background #FAF8F1, dark background #1A1A17. All chrome tokens correctly theme-adaptive. No forbidden colormaps.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above generic defaults: the combination of sorted ranking, larger top-performer dot, callout annotation with arrow, and average reference line creates a designed narrative. Not quite FiveThirtyEight-level but clearly intentional rather than out-of-the-box.
  • DE-02: Visual Refinement (4/6) — Top/right spines removed, subtle y-axis-only grid at alpha=0.15, white marker edges for definition, theme-adaptive chrome throughout. Solid refinement.
  • DE-03: Data Storytelling (4/6) — Clear ranking story via descending sort. Average line anchors the viewer's reference. "Top performer" callout creates an explicit focal point. Value labels help readers extract exact figures without axis gymnastics.

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — Correct lollipop: thin stems (ax.vlines) from baseline to value, circular markers (ax.scatter) at each data point, vertical orientation.
  • SC-02: Required Features (4/4) — Stems present, markers present, vertical orientation, data sorted by value descending.
  • SC-03: Data Mapping (3/3) — Categories on x-axis, sales values on y-axis, all 10 data points shown.
  • SC-04: Title & Legend (2/3) — Title is but the required format is . The "python" language identifier is missing. Fix: .

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all essential lollipop features: stems, markers, sorted ranking, range of values, baseline-to-dot visual.
  • DQ-02: Realistic Context (5/5) — Retail sales by category is a real-world, neutral business scenario with recognizable category labels.
  • DQ-03: Appropriate Scale (4/4) — Values 25–87K for retail category sales are realistic and well-spread.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → constants → data → plot → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — Fully deterministic hardcoded data; no random generation.
  • CQ-03: Clean Imports (2/2) — os, matplotlib.pyplot, matplotlib.ticker, numpy — all used.
  • CQ-04: Code Elegance (2/2) — Clean Pythonic code; np.where for conditional marker sizes is concise; FuncFormatter for y-tick formatting is elegant.
  • CQ-05: Output & API (1/1) — Saves as with correct dpi; no bbox_inches='tight' (correct).

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Correct axes-method API throughout (ax.vlines, ax.scatter, ax.annotate, ax.axhline). Uses FuncFormatter from matplotlib.ticker idiomatically. Subplots_adjust used correctly to avoid bbox_inches='tight' drift.
  • LM-02: Distinctive Features (3/5) — ax.vlines is the canonical matplotlib stem API for lollipops. ax.annotate with arrowprops is distinctly matplotlib. mticker.FuncFormatter is library-specific. Good use but not pushing into territory that truly couldn't be replicated in another library.

Score Caps Applied

  • None

Strengths

  • Correct lollipop chart type: stems via ax.vlines, markers via ax.scatter, vertical orientation, baseline-to-value design
  • Good data storytelling: descending sort creates natural ranking narrative, average reference line anchors comparison, "Top performer" callout annotation with arrow creates focal point
  • Brand green (#009E73) correctly used as single series color; differential marker size (s=120 top vs s=80 rest) adds emphasis
  • Theme-adaptive chrome correctly and completely implemented — all text, background, grid, annotation box tokens flip between themes
  • Clean code: no functions/classes, deterministic data, correct matplotlib axes API, no bbox_inches='tight' (respects canvas gate)

Weaknesses

  • Title missing "python" language identifier: should be — the {language} token is required by SC-04
  • Value labels (fontsize=6.5) and avg reference label (fontsize=6) are too small at mobile scale (~400px); increase value labels to fontsize=8 and avg label to fontsize=7.5
  • X-axis label "Product Category" is at the bottom canvas edge with bottom margin too tight; increase to to ensure the xlabel doesn't touch or clip the canvas edge

Issues Found

  1. SC-04 FAIL: Title format missing language identifier
    • Fix: Change to
  2. VQ-01 SMALL LABELS: Value labels and avg label font sizes too small for mobile readability
    • Fix: Increase value label fontsize from 6.5 → 8, avg label fontsize from 6 → 7.5
  3. VQ-05 BOTTOM MARGIN: X-axis label proximity to canvas edge
    • Fix: Change to

AI Feedback for Next Attempt

Three fixes needed: (1) Add "python" to title: . (2) Increase value label fontsize from 6.5 to 8 and avg label from 6 to 7.5 for mobile legibility. (3) Increase subplots_adjust bottom from 0.22 to 0.26 to give the x-axis label clear clearance from the canvas edge. The data storytelling, palette compliance, and code quality are all strong — these three targeted fixes should bring the score to ≥90.

Verdict: REJECTED

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

github-actions Bot commented Jul 1, 2026

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

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white (#FAF8F1) background — correct, not pure white. Title "lollipop-basic · python · matplotlib · anyplot.ai" in dark ink at 12pt is fully readable. X-axis label "Product Category" and Y-axis label "Sales (thousands)" in dark ink at 10pt, both clear. Ten retail category tick labels (Electronics, Clothing, etc.) rotated 45° at 8pt, all legible with no clipping. Value labels (87K, 72K, …) at 8pt in INK_SOFT gray float above each marker. Brand green (#009E73) stems and filled circular markers are prominent on the cream surface. Average reference line is dashed in INK_MUTED with "avg 52K" label at 7.5pt on the right — small but legible at full resolution. "Top performer" annotation box with arrowhead points to the Electronics lollipop. All text is readable against the light background.

Dark render (plot-dark.png): Warm near-black (#1A1A17) background — correct, not pure black. Title and axis labels render in light ink (INK = #F0EFE8 in dark mode), clearly visible against the dark surface. Tick labels appear in INK_SOFT (#B8B7B0) — muted gray that reads well on near-black. The "avg 52K" annotation uses INK_MUTED (#A8A79F) — visible. The "Top performer" annotation box uses ELEVATED_BG (#242420) fill with light INK text — a correct dark-mode adaptation. Data colors are identical to the light render: brand green #009E73 stems and markers are unchanged. No dark-on-dark failures observed; all chrome elements flip correctly.

Both paragraphs confirm both renders were reviewed. No AR-08 (fake interactivity) or AR-09 (edge clipping) violations found. Canvas gate file absent — dimensions passed (3200×1800 px landscape).

Score: 87/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — all sizes explicitly set and readable in both themes; 6.5pt annotation text is borderline at 400px mobile scale
  • VQ-02: No Overlap (6/6) — 45° rotated tick labels well-spaced; value labels clear of markers; no collisions
  • VQ-03: Element Visibility (6/6) — sparse 10-point dataset; s=80–120 markers correctly sized; stems at linewidth=2 clearly visible; edge highlights add definition
  • VQ-04: Color Accessibility (2/2) — single series in CVD-safe brand green; no red-green sole signal
  • VQ-05: Layout & Canvas (4/4) — canvas gate passed; subplots_adjust gives generous margins; canvas filled well
  • VQ-06: Axis Labels & Title (2/2) — "Product Category" and "Sales (thousands)" are descriptive with units; title format correct
  • VQ-07: Palette Compliance (2/2) — first series #009E73; backgrounds #FAF8F1/#1A1A17; all INK/INK_SOFT/INK_MUTED tokens adapt correctly

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (4/8) — well-configured default: clean, correct, uses INK hierarchy and edge highlighting on markers, but no advanced typographic or compositional moves beyond standard template
  • DE-02: Visual Refinement (4/6) — top/right spines removed; y-axis-only grid at alpha=0.15; set_axisbelow; INK_SOFT spine color; edge highlights (edgecolors=PAGE_BG) on scatter markers
  • DE-03: Data Storytelling (4/6) — sorted descending creates a clear ranking narrative; average reference line for statistical context; focal point via larger top-performer marker (s=120) + annotation callout

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — correct lollipop chart: ax.vlines() stems from baseline + ax.scatter() circular markers, vertical orientation
  • SC-02: Required Features (4/4) — thin stems, circular dots, vertical orientation, sorted by value — all spec requirements met
  • SC-03: Data Mapping (3/3) — categories on x-axis, values on y-axis, all 10 data points shown
  • SC-04: Title & Legend (3/3) — title "lollipop-basic · python · matplotlib · anyplot.ai" correct; no legend (single series, correct to omit)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — demonstrates all lollipop aspects: stems, markers, baseline, sorted order; value labels and reference line add informational depth
  • DQ-02: Realistic Context (5/5) — retail category sales data: neutral, real-world, named categories (not abstract labels)
  • DQ-03: Appropriate Scale (4/4) — 25–87K range plausible for retail; y-axis from 0 correct for lollipop/bar-type charts

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — linear: imports → data → plot → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — fully hardcoded deterministic data; no random elements
  • CQ-03: Clean Imports (2/2) — all 4 imports (os, matplotlib.pyplot, matplotlib.ticker, numpy) are used
  • CQ-04: Code Elegance (2/2) — clean Pythonic code; no fake interactivity; appropriate complexity
  • CQ-05: Output & API (1/1) — saves as plot-{THEME}.png; no bbox_inches='tight'; current matplotlib API

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — ax.vlines() for stems, ax.scatter() with edge params, ax.annotate() with arrowprops, ax.axhline(), mticker.FuncFormatter, fig.subplots_adjust() — all correct idiomatic matplotlib patterns
  • LM-02: Distinctive Features (2/5) — mticker.FuncFormatter and ax.annotate with arrowprops are matplotlib-specific; usage is moderate but doesn't showcase deeper library capabilities

Score Caps Applied

  • None — no caps triggered (DE-01=4, DE-02=4; no element is 0)

Strengths

  • Perfect spec compliance: correct lollipop anatomy (vlines stems + scatter markers), vertical orientation, value-sorted data
  • Correct Imprint palette usage with full theme-adaptive chrome threading through all INK/INK_SOFT/INK_MUTED tokens
  • Intentional visual hierarchy: size-differentiated top-performer marker, annotation callout, and average reference line create a clear ranking narrative
  • Idiomatic matplotlib: ax.vlines(), ax.annotate() with arrowprops, mticker.FuncFormatter — all proper library patterns
  • Perfect code quality: clean KISS structure, no unused imports, deterministic data, correct output naming

Weaknesses

  • Annotation text at fontsize=6.5 and avg-line label at fontsize=7.5 are borderline at mobile scale (~400px viewport) — bump both to 8pt minimum
  • DE-01 at default level: aesthetic sophistication could be elevated — e.g. subtle per-category intensity variation, refined typography, or a visual device that makes the ranking story more immediate
  • LM-02 moderate: only two genuinely matplotlib-distinctive features used (FuncFormatter, annotate with arrowprops) — could showcase more library depth

Issues Found

  1. VQ-01 MINOR: Tertiary text too small for reliable mobile legibility
    • Fix: Increase annotation fontsize from 6.5 → 8, avg-line label from 7.5 → 8
  2. LM-02 MODERATE: Limited use of matplotlib-distinctive features
    • Fix: Consider ax.patheffects for stems, custom bbox transforms for annotation positioning, or plt.rcParams for more control

AI Feedback for Next Attempt

The implementation is well above the approval threshold — spec compliance, data quality, and code quality are all perfect, and the visual design is clean with intentional storytelling through the sorted ranking + annotation + reference line. If a further repair is run, focus on: (1) bumping annotation and avg-line text to 8pt minimum for mobile safety; (2) explore one additional matplotlib-specific technique (e.g., patheffects on stems, or a custom arrow connector style) to lift LM-02; (3) consider a modest DE-01 lift via tighter typography or a design accent that makes the ranking message more visually immediate.

Verdict: APPROVED

@github-actions github-actions Bot added quality:87 Quality score 87/100 ai-approved Quality OK, ready for merge and removed quality:85 Quality score 85/100 labels Jul 1, 2026
@MarkusNeusinger MarkusNeusinger merged commit 40a72d9 into main Jul 1, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/lollipop-basic/matplotlib branch July 1, 2026 06:10
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:87 Quality score 87/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant