Skip to content

feat(plotnine): implement sankey-basic#5609

Merged
MarkusNeusinger merged 5 commits intomainfrom
implementation/sankey-basic/plotnine
Apr 30, 2026
Merged

feat(plotnine): implement sankey-basic#5609
MarkusNeusinger merged 5 commits intomainfrom
implementation/sankey-basic/plotnine

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: sankey-basic - python/plotnine

Implements the python/plotnine version of sankey-basic.

File: plots/sankey-basic/implementations/python/plotnine.py

Parent Issue: #810


🤖 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): Sankey diagram on warm off-white background (#FAF8F1). Four source nodes on the left — Coal (teal-green), Gas (orange), Nuclear (blue), Renewables (pink/mauve) — and three target nodes on the right — Industrial, Commercial, Residential — in dark charcoal grey. Curved flow bands connect sources to targets with semi-transparency (alpha0.5), widths proportional to flow values. Numerical labels appear on larger flows (35, 25, 20, 18, 15, 15, 12, 12). Title "Energy Flow · sankey-basic · plotnine · anyplot.ai" in bold dark text at top. "Sources" and "Sectors" annotations at bottom. All text is dark and clearly readable against the light background.

Dark render (plot-dark.png): Same structure on near-black background (~#1A1A17). Source node colors appear identical to light render (teal-green, orange, blue, pink — data colors unchanged ✓). Target nodes appear light grey on dark background (appropriate chrome flip). Title and node labels appear WHITE — readable against the dark background. "Sources"/"Sectors" annotations also in muted light color — readable. However, a critical discrepancy exists: the code hardcodes color="#333333" (near-black) for all node label geom_text calls and annotate statements. Near-black text on a near-black background would be invisible — yet the images show white labels. This proves the images were generated from a DIFFERENT version of the code than what is currently in the file. The code also saves to "plot.png" and does not read ANYPLOT_THEME, yet two properly-themed images exist. The code title says "pyplots.ai" but images show "anyplot.ai". These discrepancies are flagged as the primary rejection reason.

Score: 76/100

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

Visual Quality (22/30)

  • VQ-01: Text Legibility (6/8) — Sizes explicitly set (title=24, node labels=16, flow values=11). Flow value labels at size=11 are slightly small. Images show readable text in both themes, but code hardcodes #333333 labels that would be dark-on-dark in dark mode.
  • VQ-02: No Overlap (5/6) — Minimal overlap at flow crossing points; labels staggered; node labels clearly separated.
  • VQ-03: Element Visibility (5/6) — All bands visible with alpha=0.5, nodes clearly defined with white borders.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito colors (in images) are CVD-safe; semi-transparency aids distinguishing crossing flows.
  • VQ-05: Layout & Canvas (3/4) — Good canvas utilization; some bottom whitespace.
  • VQ-06: Axis Labels & Title (2/2) — Descriptive title + "Sources"/"Sectors" annotations.
  • VQ-07: Palette Compliance (0/2) — Code contains #306998 (Python Blue, explicitly non-compliant) for Coal. Coal must be #009E73. Gas uses #FFD43B, Nuclear #4ECDC4, Renewables #2ECC71 — none are Okabe-Ito. Images appear to use correct colors but code does not match.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Custom Sankey built entirely from plotnine primitives with smooth Hermite curves. Above-default polish.
  • DE-02: Visual Refinement (4/6) — No grid, no axis text/ticks, white node borders, good whitespace.
  • DE-03: Data Storytelling (4/6) — Energy flow narrative clear; flow widths encode values; numerical labels on larger flows guide the reader.

Spec Compliance (12/15)

  • SC-01: Plot Type (5/5) — Correct Sankey diagram with nodes, curved flow bands, proportional widths.
  • SC-02: Required Features (4/4) — Source-target flows, proportional widths, distinct source colors, node labels, no circular flows, link opacity.
  • SC-03: Data Mapping (3/3) — Sources left, sectors right, flow values correctly mapped to band widths.
  • SC-04: Title & Legend (0/3) — Code title says "pyplots.ai" not "anyplot.ai". Wrong branding. Must be "sankey-basic · plotnine · anyplot.ai" (or with descriptive prefix).

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 4 sources × 3 targets = 9 flows; mix of large and small; crossing bands demonstrate complexity.
  • DQ-02: Realistic Context (5/5) — Energy sector example is realistic, neutral, commonly used for Sankey demos.
  • DQ-03: Appropriate Scale (4/4) — Flow values are plausible relative proportions for energy distribution.

Code Quality (6/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → data → geometry → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — All data hardcoded — fully deterministic.
  • CQ-03: Clean Imports (1/2) — All imports used, but # noqa: E402 disable comments are present and prohibited by project rules. Restructure to avoid them.
  • CQ-04: Code Elegance (2/2) — Well-structured custom Sankey builder; no fake UI; clear logic.
  • CQ-05: Output & API (0/1) — Saves to "plot.png" not f'plot-{THEME}.png'. Does not read ANYPLOT_THEME env var. Must produce plot-light.png and plot-dark.png.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Uses ggplot grammar with aes(), geom_* layers, theme(), scale_fill_manual() correctly.
  • LM-02: Distinctive Features (3/5) — Building a full Sankey from geom_polygon + geom_rect + geom_text with custom curve math is distinctive plotnine usage.

Score Caps Applied

  • None applied (DE-01=5 > 2, DE-02=4 > 2, no "boring" cap triggered)

Strengths

  • Creative implementation of Sankey diagram using plotnine grammar of graphics primitives — no external Sankey library needed
  • Smooth cubic Hermite interpolation (3t²-2t³) for curved flow bands looks polished and professional
  • Realistic energy flow domain with plausible proportions (full marks in Data Quality)
  • Good data storytelling through flow thickness, numerical labels on larger bands, clear source/sector separation

Weaknesses

  • CRITICAL CODE/IMAGE MISMATCH: Current code saves plot.png, has no ANYPLOT_THEME handling, hardcodes color="#333333" for labels (dark-on-dark in dark mode), and uses wrong branding "pyplots.ai". The images appear to have been generated from a different, now-lost version. The code in the file must be replaced with a complete, theme-aware implementation.
  • Palette non-compliance: Replace #306998 (Python Blue) with #009E73 for Coal. Replace all source colors with Okabe-Ito order: Coal=#009E73, Gas=#D55E00, Nuclear=#0072B2, Renewables=#CC79A7.
  • Theme adaptation missing: Read ANYPLOT_THEME env var, define INK/INK_SOFT/PAGE_BG tokens, use them for all text colors and backgrounds instead of hardcoded #333333/#555555.
  • Wrong output filename: Use plot.save(f'plot-{THEME}.png', dpi=300, verbose=False).
  • noqa comments: Restructure so sys.path manipulation doesn't require # noqa: E402.

Issues Found

  1. CQ-05 FAIL + SC-04 FAIL: Output is plot.png and title says pyplots.ai — both must be fixed. Fix: read ANYPLOT_THEME, save f'plot-{THEME}.png', set title to "Energy Flow · sankey-basic · plotnine · anyplot.ai".
  2. VQ-07 = 0: #306998 Python Blue used for Coal. Fix: OKABE_ITO = ['#009E73', '#D55E00', '#0072B2', '#CC79A7', ...] and use OKABE_ITO[i] for each source in order.
  3. Dark mode label failure: color="#333333" hardcoded in geom_text and annotate calls. Fix: use INK = "#1A1A17" if THEME == "light" else "#F0EFE8" and INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" throughout.
  4. noqa comments: Move import sys and sys.path manipulation to a separate block before other imports, or use importlib — avoid disable comments.

AI Feedback for Next Attempt

Complete rewrite required. The current code is stale (pyplots.ai branding, no theme handling, wrong output filename, Python Blue palette). Rewrite with: (1) THEME = os.getenv("ANYPLOT_THEME", "light") at top, define PAGE_BG, INK, INK_SOFT tokens; (2) Okabe-Ito source colors ['#009E73', '#D55E00', '#0072B2', '#CC79A7']; (3) pass INK/INK_SOFT to all geom_text color= and annotate color= arguments; (4) plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG) in theme; (5) save as f'plot-{THEME}.png'; (6) title "Energy Flow · sankey-basic · plotnine · anyplot.ai". Keep the clever polygon-based Sankey math — it works well. Just fix the theming, palette, and output filename.

Verdict: REJECTED

@github-actions github-actions Bot added quality:76 Quality score 76/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
Attempt 1/3 - fixes based on AI review
@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): The plot renders on a warm off-white #FAF8F1 background. The title "Energy Flow · sankey-basic · plotnine · anyplot.ai" appears bold and centered in dark ink at the top. Four source nodes are stacked on the left — Coal (green #009E73), Gas (orange #D55E00), Nuclear (blue #0072B2), Renewables (pink #CC79A7) — and three target nodes (Industrial, Commercial, Residential) appear as neutral dark-gray rectangles on the right. Semi-transparent curved flow polygons connect sources to targets with widths proportional to values; flow value labels (35, 25, 20, 15, 18, 15, 12, 12) are placed in the flow midpoints. "Sources" and "Sectors" labels appear in soft ink at the bottom. All text is clearly readable against the light background.

Dark render (plot-dark.png): The same layout renders on a warm near-black #1A1A17 background. The title and node labels switch to light near-white text (#F0EFE8). The source node colors are identical to the light render — Coal green, Gas orange, Nuclear blue, Renewables pink — confirming only chrome flips. Target nodes become light gray (#B8B7B0) rectangles, creating good contrast against the dark background. Flow polygons are slightly more subdued due to alpha=0.5 over dark background, but all major flows remain clearly visible. Flow value labels and section labels render in light ink. No dark-on-dark failures detected; all text is readable against the dark background.

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

Score: 84/100

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

Visual Quality (26/30)

  • VQ-01: Text Legibility (7/8) — Title 24pt, node labels 16pt, section labels 16pt are well-sized; flow value labels at size=11 are slightly below the 16pt guideline for this canvas, but readable
  • VQ-02: No Overlap (5/6) — Minor crowding of value labels (two "15" labels) in the crossing zone, but no severe collision
  • VQ-03: Element Visibility (5/6) — All flows visible; the crossing area in the dark render is somewhat muddy with overlapping alpha flows, but the main structure is clear
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe; no red-green sole-signal issues
  • VQ-05: Layout & Canvas (3/4) — Good margins and proportions; right-side target labels slightly tight against the coord_cartesian boundary
  • VQ-06: Axis Labels & Title (2/2) — Descriptive title; no axis labels needed for Sankey; "Sources"/"Sectors" footer labels serve as orientation
  • VQ-07: Palette Compliance (2/2) — Coal = #009E73 (first series), Okabe-Ito order followed for all 4 sources, backgrounds #FAF8F1/#1A1A17 correct in both renders

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) — Thoughtful source/target color distinction (Okabe-Ito sources vs. neutral INK_SOFT targets), flow transparency, white node borders, no legend or axes — above defaults but not exceptional
  • DE-02: Visual Refinement (3/6) — Clean minimal theme with no grid/spines/axes; node sizing and positioning carefully computed; flow crossing area could benefit from tighter visual refinement
  • DE-03: Data Storytelling (3/6) — Proportional widths encode magnitude clearly; value labels on significant flows; "Sources"/"Sectors" section labels orient the viewer; but tracing individual flows through crossings is challenging

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct Sankey diagram with proportional flow links
  • SC-02: Required Features (4/4) — Proportional link widths, distinct source colors, node labels not overlapping links, no circular flows
  • SC-03: Data Mapping (3/3) — Source→Target structure correct; node heights proportional to total flow
  • SC-04: Title & Legend (3/3) — "Energy Flow · sankey-basic · plotnine · anyplot.ai" includes all required components

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 9 flows across 4 sources and 3 targets; crossing topology; value labels; proportional sizing — all aspects covered
  • DQ-02: Realistic Context (5/5) — Energy flow scenario (Coal/Gas/Nuclear/Renewables → Industrial/Commercial/Residential) is real-world plausible and neutral
  • DQ-03: Appropriate Scale (4/4) — Values 8–35, total 160, realistic distribution for energy mix

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — No functions or classes; flat procedural script
  • CQ-02: Reproducibility (2/2) — Fully deterministic hardcoded data; no random numbers
  • CQ-03: Clean Imports (2/2) — All imported symbols used; no unused imports
  • CQ-04: Code Elegance (2/2) — Appropriate complexity for hand-rolled Sankey; no fake UI elements
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png; uses current plotnine API

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Grammar of graphics composition with geom_polygon + geom_rect + geom_text + annotate layers; scale_fill_manual for explicit color mapping; coord_cartesian for bounds control
  • LM-02: Distinctive Features (3/5) — Multiple geom layer composition to build a visualization type plotnine doesn't support natively; Hermite curve interpolation for flow polygons; theme() for complete chrome control

Score Caps Applied

  • None

Strengths

  • Correct theming in both light and dark renders — source colors identical, only chrome flips (backgrounds, text, neutral node colors)
  • Smart source/target color distinction: Okabe-Ito for sources, neutral INK_SOFT for targets — clean visual hierarchy
  • All spec requirements met with realistic energy flow data (15/15 on both SC and DQ)
  • Perfect code quality: flat, deterministic, clean imports, correct output path

Weaknesses

  • Flow value labels at size=11 are slightly small for the 4800×2700 canvas — should be at least 14pt
  • Value label x-positions are offset by source index (0.35 + src_idx * 0.1) making some labels appear disconnected from their flows — consider centering on the actual flow midpoint x
  • Crossing area in the dark render appears muddy due to alpha=0.5 over dark background — slightly increasing opacity or using a lighter alpha could improve flow legibility in dark theme

Issues Found

  1. VQ-01 MINOR: Flow value labels at size=11 are below the 16pt guideline for this canvas resolution
    • Fix: Increase geom_text size for flow labels from 11 to at least 14
  2. DE-02 MODERATE: Flow label x-position formula (0.35 + src_idx * 0.1) disconnects labels from their visual flows
    • Fix: Use the actual flow polygon midpoint x instead of an index-based offset

AI Feedback for Next Attempt

Increase flow value label size to 14pt minimum. Fix value label positioning to use actual midpoint x coordinates from the flow polygon data rather than a fixed offset formula. Consider increasing flow alpha slightly (0.6) in dark theme to improve crossing area legibility.

Verdict: APPROVED

@github-actions github-actions Bot added quality:84 Quality score 84/100 ai-approved Quality OK, ready for merge labels Apr 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit b603e60 into main Apr 30, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/sankey-basic/plotnine branch April 30, 2026 09:27
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:76 Quality score 76/100 quality:84 Quality score 84/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant