Skip to content

feat(matplotlib): implement slope-basic#5637

Merged
MarkusNeusinger merged 4 commits intomainfrom
implementation/slope-basic/matplotlib
Apr 30, 2026
Merged

feat(matplotlib): implement slope-basic#5637
MarkusNeusinger merged 4 commits intomainfrom
implementation/slope-basic/matplotlib

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: slope-basic - python/matplotlib

Implements the python/matplotlib version of slope-basic.

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

Parent Issue: #981


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 30, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white #FAF8F1 background. The title "slope-basic · matplotlib · anyplot.ai" appears in dark ink at 24pt, clearly readable. The Y-axis is labeled "Sales (Millions $)" at 20pt in dark ink. The X-axis uses bold tick labels "Q1 2024" / "Q4 2024" at 20pt as the column headers. Eight product lines are drawn — 4 in brand green #009E73 (increasing products: A, C, E, G) and 4 in vermillion #D55E00 (decreasing products: B, D, F, H) — at linewidth=3 with circular markers (markersize=12) edged in the background color for crisp definition. Labels at both endpoints show product name and dollar value in bold colored text (fontsize=14) with dotted connectors where labels were nudged. A legend "Increase / Decrease" is centered near the top. All text is clearly readable against the light background — no light-on-light issues.

Dark render (plot-dark.png): The same chart renders on a warm near-black #1A1A17 surface. The title, Y-axis label, and X-axis tick labels switch to #F0EFE8 light ink — clearly readable against the dark background. Y-axis tick labels use #B8B7B0 muted light tone. The legend frame correctly uses the ELEVATED_BG #242420 fill. Data colors (green #009E73 and vermillion #D55E00) are identical to the light render — only chrome elements have flipped. The marker edge rings (now near-black on near-black) naturally blend in. Endpoint labels in green/vermillion remain clearly readable on the dark surface. No dark-on-dark failures observed. Brand green #009E73 is easily visible on the dark background.

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

Score: 88/100

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

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — Title 24pt, axis labels 20pt, tick labels 16pt all correct. Endpoint labels at fontsize=14 are slightly below the 16pt guideline but still readable in both themes.
  • VQ-02: No Overlap (5/6) — Label collision avoidance algorithm prevents overlaps effectively; moderate label density in the 13–17M range but no actual collisions.
  • VQ-03: Element Visibility (6/6) — Lines at linewidth=3 and markers at markersize=12 clearly visible; PAGE_BG edge rings add crisp definition.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito positions 1 and 2; CVD-safe; adequate contrast in both themes.
  • VQ-05: Layout & Canvas (4/4) — 16:9 landscape; xlim (−0.75, 1.75) provides generous room for endpoint labels; tight_layout applied; nothing clipped.
  • VQ-06: Axis Labels & Title (2/2) — Y-axis "Sales (Millions $)" with units; title in exact required format; time-point tick labels serve as column headers.
  • VQ-07: Palette Compliance (2/2) — First series #009E73 (increases); second series #D55E00 (decreases); backgrounds #FAF8F1/#1A1A17 correct.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Semantic color coding (green=growth, orange=decline) shows intentional hierarchy. Dotted connectors for nudged labels are a thoughtful polish detail. Above default (4) but not exceptional.
  • DE-02: Visual Refinement (4/6) — Top/right/bottom spines removed; left spine in INK_SOFT; grid at alpha=0.10 very subtle; X-axis tick marks removed (length=0); legend frame fully themed.
  • DE-03: Data Storytelling (4/6) — Direction-coded colors immediately tell which products rose/fell; dollar values at both endpoints quantify the change magnitude; crossing lines visually reveal rank changes.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct slopegraph connecting Q1 to Q4 values across two vertical axis positions.
  • SC-02: Required Features (4/4) — Labels at both endpoints ✓; direction color coding ✓; vertical axes labeled with time point names ✓; 8 entities within the 5–15 range ✓.
  • SC-03: Data Mapping (3/3) — X maps to Q1/Q4 time points; Y maps to Sales values; all 8 products fully represented.
  • SC-04: Title & Legend (3/3) — Title "slope-basic · matplotlib · anyplot.ai" exact match; legend shows Increase/Decrease.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 8 products with both endpoints; mix of 4 increases and 4 decreases; varying magnitudes.
  • DQ-02: Realistic Context (5/5) — Q1→Q4 product sales comparison is a plausible, neutral business scenario; values ($3M–$28M) are realistic.
  • DQ-03: Appropriate Scale (4/4) — Sales in millions with $ notation; sensible range for product-level quarterly revenue.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat procedural script; no functions or classes.
  • CQ-02: Reproducibility (2/2) — Fully deterministic hardcoded data; no randomness.
  • CQ-03: Clean Imports (2/2) — os, matplotlib.pyplot, matplotlib.lines.Line2D — all used.
  • CQ-04: Code Elegance (2/2) — No fake UI; label collision avoidance is justified complexity for a dense slopegraph.
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png at dpi=300; current matplotlib API throughout.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Axes methods used throughout; plt.setp for legend text; ax.tick_params correctly applied; Line2D for custom legend handles.
  • LM-02: Distinctive Features (3/5) — Line2D custom legend handles and plt.setp show above-default matplotlib knowledge; no FuncFormatter, BboxConnector, or more advanced matplotlib-specific features leveraged.

Score Caps Applied

  • None

Strengths

  • Clean semantic color coding: green (#009E73) for increases, vermillion (#D55E00) for decreases using Okabe-Ito positions 1–2
  • Label collision avoidance algorithm with dotted connectors for nudged labels — thoughtful UX for a dense slopegraph
  • Full theme-adaptive chrome: backgrounds, text, spines, legend frame, and grid all respond correctly to ANYPLOT_THEME
  • Spec-complete: labels at both endpoints with product name and dollar value, 8 entities well within the 5–15 range
  • Clean code with no functions/classes, deterministic data, and only necessary imports

Weaknesses

  • Endpoint label fontsize=14 is slightly below the recommended 16pt for secondary text at this canvas size — consider 15–16pt
  • Overall aesthetic sophistication is modest; a subtle vertical column line or faint reference zone could improve visual anchoring
  • Bottom spine removal combined with X-tick length=0 leaves the column headers floating — a thin horizontal rule at the data positions could sharpen the chart structure
  • LM-02: No use of matplotlib-specific advanced features beyond Line2D; FuncFormatter for tick labels or BboxConnector for refined label connectors could elevate this

Issues Found

  1. VQ-01 MINOR: Endpoint labels at fontsize=14 are slightly below the 16pt guideline for secondary text at this canvas scale.
    • Fix: Increase endpoint label fontsize from 14 to 15 or 16.

AI Feedback for Next Attempt

Implementation is strong — approved as-is. If regenerating: increase endpoint label fontsize from 14→16 for consistency with the secondary-text scale guideline, and consider adding one matplotlib-distinctive touch (e.g. FuncFormatter for the Y-axis tick labels to show "$Xm" format, or BboxConnector for cleaner label anchoring).

Verdict: APPROVED

@github-actions github-actions Bot added quality:88 Quality score: 88/100 ai-rejected Quality not OK, triggers update labels Apr 30, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Apr 30, 2026
@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 Apr 30, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Slope chart on warm off-white (#FAF8F1) background. Two vertical structural lines anchor Q1 2024 (left) and Q4 2024 (right) columns. Eight product lines are drawn in either brand green (#009E73) for products that increased or Okabe-Ito vermillion (#D55E00) for products that decreased. Circle markers with white edge highlighting mark endpoints. Product name + dollar value labels appear on both left and right flanks; a label-collision avoidance algorithm with dotted connectors prevents overlap. Y-axis ticks are formatted as "$XM" (e.g., $5M, $10M…$25M) in a muted ink tone. Title "slope-basic · matplotlib · anyplot.ai" renders in dark INK at top center. A two-entry legend (Increase / Decrease) floats inside an elevated-bg frame below the title. All text is clearly readable against the light background — no legibility issues found.

Dark render (plot-dark.png): The same composition on near-black (#1A1A17) background. Title, axis label, tick labels, and product labels all flip to light-colored text (F0EFE8 / B8B7B0 tokens). The data colors (#009E73 green and #D55E00 vermillion) are identical to the light render — only chrome flips. The legend frame uses the dark elevated-bg (#242420). Grid lines remain subtle at alpha=0.10 on the dark surface. No dark-on-dark text failures detected — all labels are clearly legible against the near-black background.

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

Score: 90/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (8/8) — Title 24pt, axis labels 20pt, ticks 16pt, product labels 16pt all explicitly set; readable in both themes
  • VQ-02: No Overlap (5/6) — Collision avoidance algorithm with dotted connectors handles most crowding; bottom-right pair (Product A $5.5M / Product B $4.0M) sits very close but remains readable
  • VQ-03: Element Visibility (6/6) — linewidth=3 slope lines and markersize=12 circles with white edge are optimally visible at full resolution
  • VQ-04: Color Accessibility (2/2) — #009E73 (bluish green) and #D55E00 (vermillion) are Okabe-Ito positions 1 and 2, CVD-safe by design
  • VQ-05: Layout & Canvas (4/4) — xlim extended to (-0.75, 1.75) fills margins with labels; tight_layout applied; canvas well-utilised
  • VQ-06: Axis Labels & Title (2/2) — Y-axis labelled "Sales"; units communicated inline via FuncFormatter ($XM tick labels); descriptive x-tick column headers
  • VQ-07: Palette Compliance (2/2) — Increase series = #009E73 (brand green, Okabe-Ito pos 1); Decrease = #D55E00 (pos 2); backgrounds #FAF8F1 / #1A1A17; full chrome token set applied correctly in both renders

Design Excellence (15/20)

  • DE-01: Aesthetic Sophistication (6/8) — Semantic color coding (green=up, vermillion=down) is an intentional, meaningful design choice well above generic defaults; dotted connectors and white-edge markers add polish; stops short of FiveThirtyEight-level publication quality
  • DE-02: Visual Refinement (5/6) — Top, right, and bottom spines removed; only left spine kept (appropriate for slopegraph); y-grid at alpha=0.10 is exceptionally subtle; x-tick length zeroed; legend frame themed; attention to detail is clearly visible
  • DE-03: Data Storytelling (4/6) — Color semantic encoding immediately communicates change direction; crossing lines naturally convey rank changes; viewer does not need to read numbers to understand the story; could be stronger with explicit emphasis on the most dramatic movers

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct slopegraph / slope chart
  • SC-02: Required Features (4/4) — Labels at both endpoints ✓; color-coded by direction ✓; vertical axes labelled with time-point names ✓; 8 entities within 5–15 range ✓
  • SC-03: Data Mapping (3/3) — Entities on slopes, Q1/Q4 as the two time points, y-axis shows all data
  • SC-04: Title & Legend (3/3) — Title is exactly "slope-basic · matplotlib · anyplot.ai"; legend labels "Increase" / "Decrease" match color semantics

Data Quality (14/15)

  • DQ-01: Feature Coverage (6/6) — Mix of increases and decreases; crossing lines showing rank reversals; varied magnitude of change; covers all characteristic features of a slope chart
  • DQ-02: Realistic Context (4/5) — Plausible business scenario (quarterly product sales in millions); context is clear and neutral; "Product A"–"Product H" naming is generic rather than domain-realistic
  • DQ-03: Appropriate Scale (4/4) — Sales range $3M–$28M is realistic for mid-market products; Q1→Q4 changes are proportionally credible

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → data → collision avoidance → plot → style → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — Data is hardcoded; fully deterministic
  • CQ-03: Clean Imports (2/2) — os, matplotlib.pyplot, matplotlib.ticker, matplotlib.lines.Line2D all used; no dead imports
  • CQ-04: Code Elegance (2/2) — Clean Pythonic style; collision-avoidance complexity is justified by the visual need; no fake UI
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png; current matplotlib API throughout

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (5/5) — Axes methods throughout (not pyplot); FuncFormatter for tick formatting; plt.setp for batch text styling; bbox_to_anchor legend placement; all idiomatic matplotlib patterns
  • LM-02: Distinctive Features (2/5) — FuncFormatter for currency ticks and Line2D custom legend handles are standard matplotlib tools; the collision-avoidance logic is custom Python rather than a matplotlib-distinctive feature; nothing here could not be straightforwardly replicated in another library

Score Caps Applied

  • None

Strengths

  • Semantic two-color scheme (green=increase, vermillion=decrease) immediately communicates change direction without requiring the viewer to read numbers
  • Label collision avoidance with sorted-pass algorithm and dotted connectors is a sophisticated, robust solution that works visually in both themes
  • Full chrome token adaptation: INK/INK_SOFT/ELEVATED_BG used on every non-data element; both renders are theme-correct without any dark-on-dark or light-on-light failures
  • All font sizes explicitly set (24/20/16 hierarchy); FuncFormatter provides inline unit context via "$XM" tick labels

Weaknesses

  • Generic product names ("Product A"–"H") reduce the realism of the business scenario; real product category names would score DQ-02 fully
  • LM-02: no distinctively matplotlib-native technique is used; the implementation could be ported to another library with minor syntax changes

Issues Found

  1. DQ-02 MINOR: Generic "Product A"–"H" entity names reduce scenario authenticity
    • Fix: Replace with realistic product category names (e.g., "Wireless Headphones", "Smart Watch") to earn full realism credit
  2. LM-02 LOW: FuncFormatter + Line2D are standard matplotlib; no library-distinctive technique leveraged
    • Fix: Consider using ax.secondary_xaxis for the right-column headers, or matplotlib.patheffects for label emphasis — features with no direct parallel in other libraries

AI Feedback for Next Attempt

Improve realism: replace generic "Product A–H" names with recognisable product categories or brand archetypes. To boost Library Mastery, use a distinctively matplotlib feature such as patheffects for label drop-shadows, or a custom Formatter subclass that varies tick formatting by magnitude.

Verdict: APPROVED

@github-actions github-actions Bot added quality:90 Quality score 90/100 ai-approved Quality OK, ready for merge labels Apr 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit 1503456 into main Apr 30, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/slope-basic/matplotlib branch April 30, 2026 16:54
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:88 Quality score: 88/100 quality:90 Quality score 90/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant