Skip to content

feat(bokeh): implement bar-3d-categorical#6796

Merged
MarkusNeusinger merged 5 commits into
mainfrom
implementation/bar-3d-categorical/bokeh
May 15, 2026
Merged

feat(bokeh): implement bar-3d-categorical#6796
MarkusNeusinger merged 5 commits into
mainfrom
implementation/bar-3d-categorical/bokeh

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: bar-3d-categorical - python/bokeh

Implements the python/bokeh version of bar-3d-categorical.

File: plots/bar-3d-categorical/implementations/python/bokeh.py

Parent Issue: #5248


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 15, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white (#FAF8F1) background. A 3D oblique-projection bar chart shows 5 product categories (Electronics, Apparel, Food & Bev, Books, Sports) along the front axis and 4 quarters (Q1–Q4) receding into depth. Bars are color-coded by quarter: Q1 (#009E73 green), Q2 (#D55E00 orange), Q3 (#0072B2 blue), Q4 (#CC79A7 pink). Each bar has three rendered faces (front, right, top) with darkened/lightened shades. A value axis line with tick labels (30, 60, 90, 120) appears on the left. Quarter labels (Q1–Q4) are positioned at the right edge in their respective colors. The title is clearly readable at the top. The main legibility issue is the Y-axis label "Sales (k units)" which is rendered character-by-character as individual stacked Labels — each character appears as a separate element on the left edge, creating uneven vertical spacing and making the label barely recognizable. All other text is readable. Canvas utilization is approximately 40–45% — there is significant empty space on the right side of the 4800×2700 canvas. Legibility verdict: PASS (except the Y-axis label approach is very poor aesthetically).

Dark render (plot-dark.png): The background correctly switches to near-black (#1A1A17). The title appears in light (#F0EFE8) text and is clearly readable. Tick labels and the value axis use INK_MUTED tokens (#A8A79F) and are visible against the dark surface. The data colors (Q1 green, Q2 orange, Q3 blue, Q4 pink) are identical to the light render — only chrome flips. The quarter labels (Q1–Q4) retain their Okabe-Ito colors. No "dark-on-dark" failure detected — all text elements are light enough to read against the dark surface. The character-by-character Y-axis label has the same structural problem as in the light render. Canvas utilization is the same (left-heavy, right side mostly empty). Legibility verdict: PASS (no dark-on-dark failures; same Y-axis label aesthetic issue applies).

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

Score: 76/100

Category Score Max
Visual Quality 22 30
Design Excellence 11 20
Spec Compliance 14 15
Data Quality 14 15
Code Quality 8 10
Library Mastery 7 10
Total 76 100

Visual Quality (22/30)

  • VQ-01: Text Legibility (5/8) — Font sizes explicitly set (title 26pt, ticks 16pt, labels 18–22pt). Deduction: Y-axis label is a for-loop over individual characters producing scattered, barely-readable vertical text; not a real axis label.
  • VQ-02: No Overlap (5/6) — No text collisions; minor expected bar occlusion from 3D perspective.
  • VQ-03: Element Visibility (5/6) — All bars clearly visible; base plane grid subtly present.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe; face shading adds luminance variation.
  • VQ-05: Layout & Canvas (2/4) — Chart occupies left ~40–45% of the 4800×2700 canvas; significant empty space on the right and top-right quadrant unused.
  • VQ-06: Axis Labels & Title (1/2) — Title correct and complete. Y-axis label present in concept but rendered as individual stacked characters — not a proper axis label.
  • VQ-07: Palette Compliance (2/2) — Q1=#009E73 (first series correct), Q2–Q4 follow Okabe-Ito order. Backgrounds: #FAF8F1 (light) / #1A1A17 (dark). All chrome tokens applied correctly.

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) — Genuinely impressive: custom oblique 3D projection built entirely from Bokeh patches, three-face shading with hex_darken/hex_lighten, colored quarter labels as visual legend. Deducted for the character-by-character Y-axis label (clearly visible design flaw) and poor canvas utilization.
  • DE-02: Visual Refinement (3/6) — Bokeh native axes are cleanly hidden; outline_line_color=None is tidy; base plane grid is subtle. Loses points for the awkward Y-axis label and large empty canvas area.
  • DE-03: Data Storytelling (3/6) — The 3D layout helps compare across both categorical dimensions. Quarter color-coding with matching labels is effective. No further emphasis, value callouts, or visual hierarchy guiding the viewer to the key insight.

Spec Compliance (14/15)

  • SC-01: Plot Type (5/5) — 3D bar chart with two categorical axes, correct oblique 3D simulation.
  • SC-02: Required Features (3/4) — Spacing between bars ✓, color encoding ✓, base plane grid ✓, legend ✓. Missing: value labels on top of bars — spec says "consider adding value labels on top of bars when the grid is small (under 25 bars)" and this grid has 20 bars.
  • SC-03: Data Mapping (3/3) — Products on front axis, quarters in depth, values as bar height. Correct.
  • SC-04: Title & Legend (3/3) — Title "Retail Sales by Product & Quarter · bar-3d-categorical · bokeh · anyplot.ai" correct. Quarter labels colored with Okabe-Ito colors serve as legend.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows two categorical dimensions, 5×4=20 bars, 3D face shading, base plane grid, value axis. Could add value labels for completeness.
  • DQ-02: Realistic Context (5/5) — Retail sales by product category and quarter: realistic, neutral business scenario.
  • DQ-03: Appropriate Scale (4/4) — Values 38k–134k units: plausible for quarterly retail figures across diverse product categories.

Code Quality (8/10)

  • CQ-01: KISS Structure (2/3) — Four helper functions (project, hex_darken, hex_lighten, add_patch) increase complexity beyond pure KISS; the functions are genuinely needed for the 3D projection but still deviate from the flat-script ideal.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) present; data is deterministic.
  • CQ-03: Clean Imports (2/2) — All imports used; sys path manipulation justified.
  • CQ-04: Code Elegance (1/2) — 3D projection logic is creative and clean. Deducted for the character-by-character Y-axis label loop (inelegant workaround that produces a poor result).
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png + plot-{THEME}.html via Selenium as per bokeh.md spec.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — ColumnDataSource, patches(), Label models, toolbar_location=None, correct Selenium screenshot flow. Minor deduction: the character-by-character label is not idiomatic Bokeh (should use Label with angle or a rotated text approach).
  • LM-02: Distinctive Features (3/5) — Custom 3D oblique projection using patches() is a creative, library-specific solution. Painter's algorithm via sorted iteration shows advanced Bokeh usage. Loses 2 points because the approach bypasses Bokeh's strengths (interactivity, HoverTool) in favor of a pure manual drawing approach.

Score Caps Applied

  • None — no category scored 0; DE-01=5 and DE-02=3 (cap threshold not triggered).

Strengths

  • Sophisticated 3D oblique projection built entirely with Bokeh's 2D patch primitives — genuinely impressive for a library with no native 3D support
  • Three-face bar shading (front/right/top with hex_darken/hex_lighten) creates convincing depth and dimension
  • Correct Okabe-Ito palette: Q1=#009E73 first, followed by correct order; colored quarter labels serve as an effective inline legend
  • Proper theme-adaptive chrome: backgrounds (#FAF8F1 / #1A1A17), ink tokens, and border settings all correct in both renders
  • Painter's algorithm (back-to-front rendering loop) correctly handles depth ordering

Weaknesses

  • Y-axis label is broken: "Sales (k units)" is rendered as individual characters in a for-loop (), producing scattered uneven vertical text that is barely readable — replace with a single or position the full text as one Label rotated 90°
  • Missing value labels on top of bars: spec explicitly requires them for grids under 25 bars; this has 20 bars — add annotations above each bar's top face
  • Poor canvas utilization: chart fills roughly the left 40–45% of the 4800×2700 canvas; right side is mostly empty — adjust / layout parameters to better center and scale the 3D scene across the full canvas
  • No hover interactivity: Bokeh is an interactive library — adding HoverTool with product/quarter/value data would showcase the library's distinctive strength even though a PNG screenshot is the final artifact

Issues Found

  1. VQ-01 / CQ-04 LOW: Y-axis label rendered character-by-character in a for-loop
    • Fix: Replace the block with a single
  2. SC-02 / DQ-01: Value labels missing on top of bars (spec requires them for grid < 25 bars)
    • Fix: After drawing bars, add a at each bar's top-face center: project the centroid of the top face and add with appropriate font size (~14pt)
  3. VQ-05 / DE-02: Poor canvas utilization — chart pushed to left half
    • Fix: Increase and adjust y_range, or center the 3D scene by shifting x_range to better fill the 4800-wide canvas

AI Feedback for Next Attempt

Fix the Y-axis label first (replace character loop with single rotated Label). Add value labels on top of each bar (spec requirement for 20-bar grids). Improve canvas utilization by adjusting x_range and y_range to center and scale the 3D scene across the full 4800×2700 canvas. Consider adding a HoverTool on the bar patches to showcase Bokeh's distinctive interactivity — even though the PNG is the deliverable, the HTML artifact benefits from it.

Verdict: REJECTED

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

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot displays a 3D bar chart using an oblique projection on a warm off-white (#FAF8F1) background. Five product categories (Electronics, Apparel, Food & Bev, Books, Sports) are arranged along the x-axis, and four quarters (Q1–Q4) are stacked in depth. Each bar group is colored with the Okabe-Ito palette: Q1 in green (#009E73), Q2 in orange (#D55E00), Q3 in blue (#0072B2), Q4 in pink/mauve (#CC79A7). Bars render with three-face shading (front, side, top) for depth perception. A custom vertical axis on the left shows tick marks at 30/60/90/120 with "Sales (K units)" spelled character-by-character vertically. Product labels appear at the bottom in dark ink; quarter labels appear at the right edge in their respective series colors. Value labels are rendered on top of each bar. The title "Retail Sales by Product & Quarter · bar-3d-categorical · bokeh · anyplot.ai" is centered at the top. All text is clearly readable against the light background. Legibility verdict: PASS.

Dark render (plot-dark.png): The same chart renders on a warm near-black (#1A1A17) background. All data colors are identical to the light render — Q1 green, Q2 orange, Q3 blue, Q4 mauve — confirming only chrome flips between themes. Title, product labels, tick labels, and value annotations are rendered in light ink and are fully readable. Quarter labels retain their Okabe-Ito series colors. The bar face shading remains consistent, and the base-plane grid is visible at low alpha. No dark-on-dark failures detected — all text elements use theme-adaptive ink tokens. Legibility verdict: PASS.

Both renders pass theme-readability checks. The 3D perspective leaves some whitespace imbalance (empty upper-right quadrant), and the character-by-character vertical axis label is functional but slightly inelegant.

Score: 86/100

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

Visual Quality (26/30)

  • VQ-01: Text Legibility (6/8) — All sizes explicitly set; title at 26pt (guideline: 28pt) and axis label at 17pt (guideline: 22pt) are slightly below spec, but fully readable in both themes
  • VQ-02: No Overlap (5/6) — No text collisions; minor natural depth-ordering occlusion in 3D perspective (inherent to the chart type)
  • VQ-03: Element Visibility (6/6) — All bars clearly visible with 3-face shading; spacing between bars is well calibrated
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe; luminance contrast between faces is adequate
  • VQ-05: Layout & Canvas (3/4) — The oblique projection leaves notable empty space in the upper-right quadrant; chart occupies ~45% of canvas with imbalanced right margin
  • VQ-06: Axis Labels & Title (2/2) — "Sales (K units)" on value axis, descriptive product and quarter labels present
  • VQ-07: Palette Compliance (2/2) — Q1=#009E73 (brand green, first series) ✓, canonical Okabe-Ito order ✓, backgrounds #FAF8F1 / #1A1A17 ✓, data colors identical across themes ✓

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — Custom oblique 3D projection with hex_darken/hex_lighten face shading is a clear step above defaults; colored series labels as legend substitute shows intentional hierarchy; custom axis with tick marks replaces Bokeh chrome elegantly
  • DE-02: Visual Refinement (4/6) — Toolbar disabled, standard Bokeh axes hidden, subtle base-plane grid at 12% alpha, bar edges use PAGE_BG for definition; deducted for the character-by-character vertical axis label which is functional but inelegant vs. a proper rotated label
  • DE-03: Data Storytelling (4/6) — Bar height variation creates natural visual hierarchy (Electronics Q4 at 134 stands out); colored quarter labels guide the viewer across the depth dimension; no explicit annotation or focal-point emphasis beyond the data itself

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — 3D bar chart with two categorical axes and height encoding; bars rise from the 2D grid ✓
  • SC-02: Required Features (4/4) — Spacing between bars ✓, color encoding per quarter ✓, base-plane grid lines ✓, value labels on top (20 bars, under 25 threshold) ✓, oblique viewing angle ✓
  • SC-03: Data Mapping (3/3) — Products on x, quarters on depth-y, sales values on z; all 20 data points rendered ✓
  • SC-04: Title & Legend (3/3) — Title format "{description} · bar-3d-categorical · bokeh · anyplot.ai" ✓; colored Q1–Q4 side labels serve as a clear legend substitute ✓

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Full 5×4 grid covering all combinations; values span 38–134 showing meaningful variation across both dimensions; 3-face bar shading demonstrates depth perception ✓
  • DQ-02: Realistic Context (5/5) — Retail sales by product category and quarter is a real-world, neutral, comprehensible scenario ✓
  • DQ-03: Appropriate Scale (4/4) — Values range 38–134 thousand units; plausible differences between product types (Electronics highest, Books lowest) match real-world intuition ✓

Code Quality (9/10)

  • CQ-01: KISS Structure (2/3) — Four helper functions (project, hex_darken, hex_lighten, add_patch) are justified for the oblique 3D math, but the structure departs from the flat Imports→Data→Plot→Save ideal
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set; data array is hardcoded and deterministic ✓
  • CQ-03: Clean Imports (2/2) — All imports (numpy, bokeh.io, bokeh.models, bokeh.plotting, selenium, time, pathlib, os, sys) are used ✓
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic; painter's algorithm for depth ordering is a legitimate technique; no fake UI or over-engineering ✓
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.html and plot-{THEME}.png via Selenium; follows the prescribed pattern ✓

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — ColumnDataSource, p.patches() for polygon rendering, Label models for custom text placement, figure theming properties — all idiomatic Bokeh patterns
  • LM-02: Distinctive Features (3/5) — p.patches() with ColumnDataSource for multi-polygon 3D bar rendering is a Bokeh strength; HTML export + Selenium screenshot follows the library's recommended pattern; however, no HoverTool or interactive data binding is used, which is Bokeh's most distinctive capability

Score Caps Applied

  • None — DE-01=6 and DE-02=4, neither cap condition applies

Strengths

  • Custom oblique 3D projection using Bokeh's patches glyph is technically impressive and demonstrates deep library knowledge
  • Three-face bar shading (hex_darken/hex_lighten) creates convincing depth perception without any external 3D library
  • Full Okabe-Ito compliance with correct color ordering; identical data colors in both themes; correct background tokens
  • Painter's algorithm for depth-correct bar rendering is correctly implemented
  • Value labels on all 20 bars add practical readability without cluttering the chart

Weaknesses

  • Axis label font size (17pt) and title font size (26pt) are below the 22pt / 28pt guidelines for pixel-based Bokeh at 4800px
  • Character-by-character vertical axis label is inelegant — a rotated text approach or label reformatting would be cleaner
  • Canvas whitespace is unbalanced — significant empty area in upper-right due to the oblique projection not filling the canvas; x_range could be tightened or the plot offset adjusted
  • No HoverTool on the HTML output — missed opportunity to use Bokeh's most distinctive feature, even just for showing product/quarter/value on hover

Issues Found

  1. VQ-01 / VQ-06 LOW: Title 26pt (< 28pt) and axis label 17pt (< 22pt guideline for Bokeh)
    • Fix: Set ; increase the per-character label font size to at least 20pt or restructure as a normal side label using a y-positioned Label with
  2. VQ-05 PARTIAL: Empty upper-right canvas quadrant
    • Fix: Tighten right bound or shift the plot origin so the 3D chart is more centered on the canvas
  3. LM-02 MISSED: No HoverTool on the interactive HTML artifact
    • Fix: Add a to the patches glyph with tooltips showing product, quarter, and sales value

AI Feedback for Next Attempt

Increase title to 28pt and the value-axis label font to at least 20pt. Restructure the vertical axis label as a single rotated Bokeh Label (angle=π/2) rather than character-by-character. Tighten the x_range right bound (reduce by ~1.5–2 units) to reduce the empty upper-right whitespace. Optionally add a HoverTool to the patches source for the interactive HTML — it would significantly boost Library Mastery without requiring changes to the PNG output.

Verdict: APPROVED

@github-actions github-actions Bot added quality:86 Quality score 86/100 ai-approved Quality OK, ready for merge and removed quality:76 Quality score 76/100 labels May 15, 2026
@MarkusNeusinger MarkusNeusinger merged commit 30d4df3 into main May 15, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/bar-3d-categorical/bokeh branch May 15, 2026 09:17
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