Skip to content

feat(bokeh): implement sankey-basic#5602

Merged
MarkusNeusinger merged 4 commits intomainfrom
implementation/sankey-basic/bokeh
Apr 30, 2026
Merged

feat(bokeh): implement sankey-basic#5602
MarkusNeusinger merged 4 commits intomainfrom
implementation/sankey-basic/bokeh

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: sankey-basic - python/bokeh

Implements the python/bokeh version of sankey-basic.

File: plots/sankey-basic/implementations/python/bokeh.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): The plot renders on a warm off-white #FAF8F1 surface. The Sankey diagram shows five energy sources on the left (Solar, Hydro, Nuclear, Gas, Coal, ordered bottom-up with Coal at the bottom) and three destination sectors on the right (Commercial, Residential, Industrial). Source nodes are colored in Okabe-Ito order: Coal uses #009E73 (teal-green), Gas uses #D55E00 (orange), Nuclear uses #0072B2 (blue), Hydro uses #CC79A7 (mauve), Solar uses #E69F00 (amber). Target nodes use muted neutral greys. The bezier flow ribbons carry source colors with fill_alpha=0.45, giving a pleasant translucent look on the light surface. All node labels (e.g. "Gas (65 TWh)") are rendered in dark INK at 22pt, clearly readable. The centered title reads "Energy Flow · sankey-basic · bokeh · anyplot.ai" at 32pt. All text is readable against the light background. Legibility verdict: PASS.

Dark render (plot-dark.png): The plot renders on a near-black #1A1A17 surface. Source/target node colors are identical to the light render (data colors are theme-invariant). Node labels and title switch to the light INK token (#F0EFE8), all readable against the dark background — no dark-on-dark failures. However, the fixed fill_alpha=0.45 on the bezier flow ribbons causes noticeably reduced visibility in dark mode: where the light background allowed the colors to bloom, the dark surface absorbs them, making crossing flows appear murky and harder to distinguish. The Industrial and Residential target node blocks are dark grey and barely contrast with the dark background. Legibility verdict: PASS (text), but flow elements have reduced visual quality.

Score: 86/100

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

Visual Quality (28/30)

  • VQ-01: Text Legibility (8/8) — title at 32pt, node labels at 22pt; both exceed pixel-based minimums; all text readable in both themes
  • VQ-02: No Overlap (6/6) — source and target labels are cleanly separated; no text collisions
  • VQ-03: Element Visibility (5/6) — flows are clear in light mode; dark mode flow visibility is reduced because fixed fill_alpha=0.45 is not compensated for the dark background
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette, colorblind-safe; alpha provides differentiation
  • VQ-05: Layout & Canvas (3/4) — diagram fills canvas well horizontally; approximately 10% of vertical height is unused empty space between the title and the top node
  • VQ-06: Axis Labels & Title (2/2) — axes hidden (correct for Sankey); node labels include units (TWh); descriptive
  • VQ-07: Palette Compliance (2/2) — first source (Coal) correctly uses #009E73; Okabe-Ito followed in canonical order; backgrounds #FAF8F1/#1A1A17; chrome is theme-adaptive

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — thoughtful design: source colors carried through bezier ribbons enables visual tracing; muted neutral target nodes create deliberate hierarchy (colorful sources → neutral destinations); proportional node sizing is precise; warm palette/backgrounds; not quite publication-ready due to the limited visual storytelling
  • DE-02: Visual Refinement (4/6) — axes/spines/grid fully removed, very clean; but vertical canvas distribution has notable dead zone at top; dark render flow murkiness slightly mars the refinement
  • DE-03: Data Storytelling (4/6) — source-color-coded flows allow the viewer to trace each energy source across the diagram; Gas dominance (65 TWh) is apparent from node size; no additional emphasis (e.g., annotation on the largest flow path)

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — correct Sankey diagram with Bezier flow ribbons and proportional node heights
  • SC-02: Required Features (4/4) — sources/targets/values mapped; proportional flow widths; distinct source colors; link opacity; node labels; no circular flows
  • SC-03: Data Mapping (3/3) — sources on left, targets on right; all 11 flows represented; node heights proportional to totals
  • SC-04: Title & Legend (2/3) — title is "Energy Flow · sankey-basic · bokeh · anyplot.ai"; required format is {spec-id} · {library} · anyplot.ai (i.e., "sankey-basic · bokeh · anyplot.ai") — extra "Energy Flow ·" prefix is non-conforming; no legend needed (nodes are labeled directly)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 11 flows from 5 sources to 3 sectors; varied flow magnitudes (5–30 TWh); multiple many-to-many connections shown; all core Sankey features exercised
  • DQ-02: Realistic Context (5/5) — energy flow domain (Coal, Gas, Nuclear, Hydro, Solar → Industrial, Residential, Commercial) is real-world, neutral, and comprehensible
  • DQ-03: Appropriate Scale (4/4) — relative magnitudes are plausible for an energy grid; Gas as the largest source (65 TWh) and Industrial as the largest consumer (58 TWh) are realistic proportions

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — clean flat script: imports → tokens → data → layout calculations → plot → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — all data is hardcoded; deterministic
  • CQ-03: Clean Imports (2/2) — all imports are used; numpy, bokeh.io, bokeh.models, bokeh.plotting
  • CQ-04: Code Elegance (2/2) — appropriate complexity for a manual Sankey; Bezier math is clear and well-structured; no fake functionality
  • CQ-05: Output & API (1/1) — saves plot-{THEME}.png and plot-{THEME}.html; current Bokeh API

Library Mastery (5/10)

  • LM-01: Idiomatic Usage (3/5) — uses figure, quad, patch, Label, export_png, output_file/save correctly; however bypasses ColumnDataSource entirely (Bokeh's core data pattern) and passes raw arrays directly
  • LM-02: Distinctive Features (2/5) — creatively assembles a Sankey from Bokeh primitives (patch for ribbons, quad for nodes); but Bokeh's signature strength — interactive hover tooltips via HoverTool — is completely absent even though an HTML file is generated; a HoverTool showing flow source/target/value on hover would be the obvious Bokeh-distinctive addition

Score Caps Applied

  • None applied

Strengths

  • Correct Sankey topology: proportional node sizing, stacked flow packing, Bezier curves all computed correctly
  • Okabe-Ito canonical order strictly followed; first source (Coal) correctly gets #009E73
  • Clean, flat code with clear layout arithmetic that is easy to follow
  • Thoughtful target-node color choice (muted neutrals) creates visual hierarchy between source and destination
  • Both PNG and HTML output generated correctly

Weaknesses

  • Title format is "Energy Flow · sankey-basic · bokeh · anyplot.ai" — must be exactly "sankey-basic · bokeh · anyplot.ai" per spec
  • Bokeh's HoverTool not used: the HTML output supports interactivity but no tooltips are added; hover showing source→target flow value is the single most impactful Bokeh-specific feature for a Sankey
  • Fixed fill_alpha=0.45 is not theme-adaptive: flows look appropriately translucent on light background but become murky/dark on dark background; use a higher alpha for dark theme
  • Dark-mode target node colors (#5A6A7A, #7A6A8A, #6A7A5A) are near-black on a near-black background — low contrast in dark render
  • Approximately 10% of canvas height is empty dead space between title and the first (top) node; compress y_range or adjust layout to use space better
  • No ColumnDataSource used — bypasses Bokeh's core data-binding pattern (less idiomatic)

Issues Found

  1. SC-04 PARTIAL: Title has extra prefix — change to "sankey-basic · bokeh · anyplot.ai"
  2. LM-02 LOW: No HoverTool added to the Bokeh figure — add a tooltip for patch elements showing source, target, and TWh value; this would be the most distinctive Bokeh feature
  3. VQ-03 DARK: flow fill_alpha=0.45 is not adaptive — use fill_alpha=0.55 if THEME == "dark" else 0.45 so flows remain vivid against dark background
  4. VQ-07 PARTIAL: dark-mode target node colors are too close to background — consider slightly lighter neutral fills for dark theme (e.g., use INK_SOFT at 20% opacity, or explicit dark-mode target colors)
  5. VQ-05: Reduce empty space at top — either adjust y_range upper bound or padding_y to compact the layout

AI Feedback for Next Attempt

Fix title to "sankey-basic · bokeh · anyplot.ai". Add a HoverTool to the figure with a tooltip for the patch glyphs showing the source, target, and value — this is Bokeh's biggest differentiator and should not be skipped. Make fill_alpha theme-adaptive (higher in dark mode ~0.55-0.65). Give target nodes brighter fills in dark mode so they don't disappear against the dark background. Tighten the vertical layout by reducing the gap between title and top node.

Verdict: REJECTED

@github-actions github-actions Bot added quality:86 Quality score 86/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): The plot renders on a warm off-white #FAF8F1 background. The title "Energy Flow · sankey-basic · bokeh · anyplot.ai" appears at 32pt centered at the top in dark ink. Five source nodes are arranged vertically on the left: Solar (yellow/golden #E69F00), Hydro (reddish-purple #CC79A7), Nuclear (blue #0072B2), Gas (orange #D55E00), and Coal (teal #009E73) — correctly following Okabe-Ito canonical order with Coal as first series. Three target nodes on the right (Commercial, Residential, Industrial) use muted neutral colors. Bezier flow ribbons carry each source's Okabe-Ito color with fill_alpha=0.45, creating a translucent layered effect where ribbons cross. All 22pt node labels (with TWh values) are clearly readable. All text is readable against the light background. PASS.

Dark render (plot-dark.png): The background is near-black #1A1A17. Title and node labels switch correctly to the light INK token (#F0EFE8) — all readable, no dark-on-dark text failure detected. Source node data colors are identical to the light render (Okabe-Ito unchanged). However, the fixed fill_alpha=0.45 is not theme-adaptive: on the dark background the semi-transparent ribbons appear noticeably darker/murkier, making crossing ribbons harder to distinguish than in light mode. Target node colors (#5A6A7A, #7A6A8A, #6A7A5A) are mid-range grays that have reduced — though still acceptable — contrast against the near-black background. Text legibility PASS; data element visibility PARTIAL due to non-adaptive alpha.

Score: 86/100

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

Visual Quality (28/30)

  • VQ-01: Text Legibility (8/8) — Title 32pt, node labels 22pt; explicitly set; readable in both themes
  • VQ-02: No Overlap (6/6) — Source and target labels cleanly separated; no text collisions
  • VQ-03: Element Visibility (5/6) — Clear in light mode; dark mode flows reduced by non-adaptive fill_alpha=0.45
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe
  • VQ-05: Layout & Canvas (3/4) — Good horizontal fill; ~10% empty vertical space between title and top node
  • VQ-06: Axis Labels & Title (2/2) — Axes hidden (correct for Sankey); node labels include TWh units
  • VQ-07: Palette Compliance (2/2) — First source (Coal) uses #009E73; Okabe-Ito canonical order; backgrounds #FAF8F1/#1A1A17; theme-adaptive chrome

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — Source colors carried through bezier ribbons create visual identity; muted neutral targets create clear source-vs-destination hierarchy; proportional sizing; polished but not quite publication-ready
  • DE-02: Visual Refinement (4/6) — All axes, spines, grid, and outline removed; clean look appropriate for Sankey; docked by vertical dead zone at top and dark-render murkiness
  • DE-03: Data Storytelling (4/6) — Source-color-coded flows allow the eye to trace individual energy streams; Gas dominance and Coal-to-Industrial pathway are immediately legible through relative ribbon sizes

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — Correct Sankey diagram with Bezier ribbons and proportional node heights
  • SC-02: Required Features (4/4) — Proportional flows; distinct source colors; link opacity; node labels with units; no circular flows
  • SC-03: Data Mapping (3/3) — Sources left, targets right; all 11 flows represented; proportional node heights
  • SC-04: Title & Legend (2/3) — Title "Energy Flow · sankey-basic · bokeh · anyplot.ai" has an extra prefix; required format is exactly "sankey-basic · bokeh · anyplot.ai"

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — 11 flows, 5 sources, 3 sectors; varied magnitudes (5–30 TWh); many-to-many connections showcase Sankey's core capability
  • DQ-02: Realistic Context (5/5) — Energy flow domain (Coal/Gas/Nuclear/Hydro/Solar → Industrial/Residential/Commercial) is real-world and neutral
  • DQ-03: Appropriate Scale (4/4) — Relative magnitudes plausible; Gas as largest source, Industrial as largest consumer are realistic

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script: imports → tokens → data → layout → plot → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — All data hardcoded; fully deterministic
  • CQ-03: Clean Imports (2/2) — All imports used: os, sys, numpy, bokeh.io, bokeh.models, bokeh.plotting
  • CQ-04: Code Elegance (2/2) — Appropriate complexity for manual Sankey; Bezier math clear and correct; no fake functionality
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html; current Bokeh 3.x API

Library Mastery (5/10)

  • LM-01: Idiomatic Usage (3/5) — Uses figure, quad, patch, Label, export_png, output_file, save correctly; bypasses ColumnDataSource (Bokeh's core data-binding pattern)
  • LM-02: Distinctive Features (2/5) — Creative use of low-level primitives to build a Sankey that Bokeh lacks natively; but HoverTool is completely absent from the HTML output — displaying source→target flow values on hover is Bokeh's signature interactive feature and the most impactful library-specific enhancement possible here

Score Caps Applied

  • None

Strengths

  • Correct Sankey topology: proportional node sizing, stacked flow packing, Bezier curves all computed correctly
  • Okabe-Ito canonical order strictly followed; first source (Coal) correctly gets #009E73
  • Clean, flat code with clear layout arithmetic that is easy to follow
  • Thoughtful target-node color choice (muted neutrals) creates visual hierarchy between source and destination
  • Both PNG and HTML output generated correctly; theme-adaptive chrome (backgrounds, text colors) properly applied in both renders

Weaknesses

  • Title format is "Energy Flow · sankey-basic · bokeh · anyplot.ai" — must be exactly "sankey-basic · bokeh · anyplot.ai" per spec
  • Bokeh HoverTool completely absent from HTML output — hover showing source→target flow value is Bokeh's signature interactive feature and a major missed opportunity for LM-02
  • Fixed fill_alpha=0.45 is not theme-adaptive: flows look translucent on light background but become murky on dark background; dark theme should use higher alpha (~0.65)
  • Approximately 10% of canvas height is empty dead space between title and the first node; tighten y_range or layout padding

Issues Found

  1. SC-04 PARTIAL: Title has extra "Energy Flow · " prefix
    • Fix: Change title= to "sankey-basic · bokeh · anyplot.ai"
  2. LM-02 LOW: HoverTool absent from HTML output
    • Fix: Add HoverTool with a @source→@target: @value TWh tooltip on the flow patches using a ColumnDataSource
  3. VQ-03 / DE-02: Fixed fill_alpha=0.45 not theme-adaptive
    • Fix: FLOW_ALPHA = 0.45 if THEME == "light" else 0.65
  4. VQ-05: Dead vertical space
    • Fix: Tighten y_range from (-5, 108) to (-3, 103) or reduce padding_y

AI Feedback for Next Attempt

Fix the title to exactly "sankey-basic · bokeh · anyplot.ai". Add HoverTool to the flow patches using ColumnDataSource — this alone lifts LM-02 from 2 to 4-5 and is the most impactful change. Make fill_alpha theme-adaptive (0.45 light / 0.65 dark). Reduce the vertical dead space between the title and the top node.

Verdict: APPROVED

@github-actions github-actions Bot added the ai-approved Quality OK, ready for merge label Apr 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit 289b7ae into main Apr 30, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/sankey-basic/bokeh branch April 30, 2026 09:14
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:86 Quality score 86/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant