Skip to content

feat(bokeh): implement ecdf-basic#5358

Merged
github-actions[bot] merged 5 commits intomainfrom
implementation/ecdf-basic/bokeh
Apr 24, 2026
Merged

feat(bokeh): implement ecdf-basic#5358
github-actions[bot] merged 5 commits intomainfrom
implementation/ecdf-basic/bokeh

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: ecdf-basic - python/bokeh

Implements the python/bokeh version of ecdf-basic.

File: plots/ecdf-basic/implementations/python/bokeh.py

Parent Issue: #976


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 24, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot shows an ECDF for "Marathon Finish Times" on a warm off-white background (~#FAF8F1). The step function is rendered in #009E73 brand green, progressing from ~165 minutes at y=0.0 to ~350 minutes at y=1.0 across 200 data points, with individual step markers visible at each point. X-axis label reads "Finish Time (minutes)" and y-axis reads "Cumulative Proportion of Runners", both in dark readable text. Title "Marathon Finish Times · ecdf-basic · bokeh · anyplot.ai" is displayed in bold dark text. Grid lines appear on both axes in a dashed style. All text is readable against the light background. No legend (correct for single-series).

Dark render (plot-dark.png): The same ECDF is rendered on a near-black background (~#1A1A17). Brand green #009E73 line is identical to the light render — data colors consistent, only chrome flips. Title and axis labels render in light/white text, clearly readable against the dark surface. Tick labels appear in lighter gray. Grid lines are subtle on the dark background. No dark-on-dark text failures observed — all text elements are appropriately light-colored.

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

Score: 78/100

Category Score Max
Visual Quality 27 30
Design Excellence 9 20
Spec Compliance 15 15
Data Quality 14 15
Code Quality 8 10
Library Mastery 5 10
Total 78 100

Visual Quality (27/30)

  • VQ-01: Text Legibility (7/8) — Font sizes explicitly set for title, axis labels, and tick labels; all readable in both themes. Minor deduction for slightly tight long title at 4800px width.
  • VQ-02: No Overlap (6/6) — No overlapping text or visual elements
  • VQ-03: Element Visibility (5/6) — ECDF step line clearly visible; individual step markers at each of 200 data points create slightly dotted appearance rather than a clean step line
  • VQ-04: Color Accessibility (2/2) — #009E73 on both light and dark backgrounds is CVD-safe with strong contrast
  • VQ-05: Layout & Canvas (3/4) — Plot fills canvas well; minor empty whitespace on far right beyond the data range
  • VQ-06: Axis Labels & Title (2/2) — "Finish Time (minutes)" and "Cumulative Proportion of Runners" are descriptive with context/units
  • VQ-07: Palette Compliance (2/2) — Images show correct #009E73 first series and theme-appropriate backgrounds/chrome. ⚠️ NOTE: Code on disk uses legacy #306998 (Python Blue) and lacks ANYPLOT_THEME support — significant discrepancy between the code file and the rendered images.

Design Excellence (9/20)

  • DE-01: Aesthetic Sophistication (4/8) — Clean single-series ECDF with brand green; looks like a well-configured library default. No exceptional design choices or visual personality.
  • DE-02: Visual Refinement (3/6) — Background color and grid alpha/dash are customized. However, all 4 spines remain visible as a box outline (top and right should be removed); both x and y grid axes active with dashed lines (y-only would be cleaner for an ECDF).
  • DE-03: Data Storytelling (2/6) — ECDF displayed correctly but without visual hierarchy. No annotation of key percentiles (25th, 50th, 75th) that would help readers extract percentile values at a glance.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct ECDF step function plot
  • SC-02: Required Features (4/4) — Step function increases 1/n per data point ✓, Y-axis 0–1 ✓, grid lines present ✓, distinct line style ✓
  • SC-03: Data Mapping (3/3) — X = finish time value, Y = cumulative proportion; correct ECDF axis assignment
  • SC-04: Title & Legend (3/3) — "Marathon Finish Times · ecdf-basic · bokeh · anyplot.ai" contains all required elements; no legend is correct for single-series

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows ECDF from 0 to 1 with proper S-curve shape revealing distribution characteristics; could additionally annotate key percentile reference points
  • DQ-02: Realistic Context (5/5) — Marathon finish times is a real, neutral, relatable scenario with clear real-world meaning
  • DQ-03: Appropriate Scale (4/4) — Values 160–350 minutes are realistic for marathon finish times across recreational runners

Code Quality (8/10)

  • CQ-01: KISS Structure (3/3) — Sequential import → data → plot → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) present
  • CQ-03: Clean Imports (2/2) — All imports used
  • CQ-04: Code Elegance (1/2) — Clean sequential structure, but lacks ANYPLOT_THEME environment variable support (required for all implementations); old pyplots.ai branding in title string
  • CQ-05: Output & API (0/1) — Code saves to bare "plot.png" / "plot.html" instead of required "plot-{THEME}.png" / "plot-{THEME}.html"

Library Mastery (5/10)

  • LM-01: Idiomatic Usage (3/5) — ColumnDataSource and figure() used correctly; follows standard bokeh patterns
  • LM-02: Distinctive Features (2/5) — HTML export is a bokeh-distinctive feature; ColumnDataSource is idiomatic. However, no HoverTool or interactive callbacks — bokeh's primary strength is not leveraged.

Score Caps Applied

  • None

Strengths

  • Marathon finish times context is engaging, realistic, and neutral — a strong real-world scenario for an ECDF
  • Brand green (#009E73) used correctly in rendered images; data color is consistent across light and dark themes
  • Correct ECDF step function construction — cumulative proportion from 0 to 1 with proper S-curve shape
  • Both theme renders are readable with no dark-on-dark or light-on-light text failures

Weaknesses

  • Critical code mismatch: Implementation file on disk uses legacy #306998 color, saves to bare plot.png/plot.html, uses pyplots.ai branding in title string, and has no ANYPLOT_THEME support — does not match the rendered images
  • All 4 spines visible as a box outline; style guide requires removing top and right spines
  • Both x and y grid axes active; y-only grid would be cleaner for an ECDF visualization
  • No annotation of key percentiles (25th, 50th, 75th) to guide data interpretation
  • Bokeh's interactivity not leveraged — no HoverTool on the HTML output

Issues Found

  1. CQ-05 FAIL / CQ-04 LOW: Code saves to "plot.png" / "plot.html" and lacks ANYPLOT_THEME support
    • Fix: Read THEME = os.getenv("ANYPLOT_THEME", "light"), apply full theme tokens per prompts/library/bokeh.md, save to f"plot-{THEME}.png" and f"plot-{THEME}.html"
  2. VQ-07 CODE ISSUE: Code uses line_color="#306998" (legacy Python Blue) instead of #009E73; title string contains pyplots.ai instead of anyplot.ai
    • Fix: Replace #306998 with "#009E73"; update title to f"Marathon Finish Times · ecdf-basic · bokeh · anyplot.ai" (or use the theme-derived approach)
  3. DE-02 LOW: All 4 spines visible as box, dashed grid on both axes
    • Fix: Set p.outline_line_color = None to remove box outline; disable x-grid (p.xgrid.grid_line_color = None); keep y-grid only with subtle alpha
  4. LM-02 LOW: No interactive features despite bokeh being an interactive library
    • Fix: Add HoverTool with @x{0.0} min and @y{0.0%} cumulative proportion display — leverages bokeh's unique interactive HTML output

AI Feedback for Next Attempt

Rebuild to meet current anyplot.ai standards: (1) Read ANYPLOT_THEME = os.getenv("ANYPLOT_THEME", "light") and apply full theme tokens (PAGE_BG, INK, INK_SOFT, ELEVATED_BG) from prompts/library/bokeh.md; save to plot-{THEME}.png and plot-{THEME}.html. (2) Use line_color="#009E73" for the ECDF line. (3) Remove the box outline (p.outline_line_color = None) and disable x-grid (p.xgrid.grid_line_color = None), keeping only a subtle y-axis grid. (4) Add a HoverTool showing finish time and cumulative proportion to leverage bokeh's interactive HTML strength. (5) Optionally annotate 25th, 50th, and 75th percentile reference lines to guide the viewer to key ECDF readings.

Verdict: REJECTED

@github-actions github-actions Bot added quality:78 Quality score 78/100 ai-rejected Quality not OK, triggers update labels Apr 24, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Apr 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/3

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 24, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1) correct. Title "Marathon Finish Times · ecdf-basic · bokeh · anyplot.ai" in bold dark text at top-left — clearly visible. Y-axis label "Cumulative Proportion of Runners" (rotated) and X-axis label "Finish Time (minutes)" both readable. Tick labels in medium-dark secondary text on both axes. Single ECDF step line in brand green (#009E73) at line_width=4 traces a clean S-curve from ~130 to ~375 minutes. Three dashed vertical reference lines in INK_SOFT gray mark the 25th (~218 min), 50th/median (~242 min), and 75th (~260 min) percentiles, with italic annotation labels at y=0.03. Y-axis grid at 10% alpha is subtle. No box outline. All text is readable against the light background — no light-on-light failures.

Dark render (plot-dark.png): Near-black background (#1A1A17) correct. Title and axis labels render in light (#F0EFE8) text — clearly visible. Tick labels in lighter secondary tone (#B8B7B0) — all readable with no dark-on-dark failures. ECDF step line remains identical brand green (#009E73), confirming Okabe-Ito data colors are theme-independent. Dashed reference lines and annotation labels in #B8B7B0 are readable against the dark surface. Y-only grid subtle at 10% alpha. All text is readable against the dark background — no dark-on-dark failures detected.

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

Score: 87/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (8/8) — All sizes explicitly set: title 28pt, axis labels 22pt, tick labels 18pt, annotations 20pt; all readable in both themes
  • VQ-02: No Overlap (5/6) — 50th and 75th percentile labels are only ~18 minutes apart on the x-axis; minor crowding risk at full 4800px resolution
  • VQ-03: Element Visibility (6/6) — ECDF line at line_width=4 clearly visible; reference spans and labels all readable
  • VQ-04: Color Accessibility (2/2) — Single brand green series on neutral background; excellent contrast, CVD-safe
  • VQ-05: Layout & Canvas (4/4) — 4800×2700 canvas well utilized, balanced margins, nothing cut off
  • VQ-06: Axis Labels & Title (2/2) — "Finish Time (minutes)" and "Cumulative Proportion of Runners" — descriptive with units
  • VQ-07: Palette Compliance (2/2) — First series #009E73 correct; backgrounds #FAF8F1/#1A1A17 correct; all chrome theme-adaptive in both renders

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (4/8) — Well-configured library default: brand green ECDF on themed chrome is correct but not exceptional. No area fill under curve, no distinctive typographic treatment, no visual flair that elevates it beyond a well-tuned default.
  • DE-02: Visual Refinement (3/6) — No box outline, y-only grid at 10% alpha, minor ticks removed — meaningfully above defaults, but generous min_border padding and refined whitespace are missing
  • DE-03: Data Storytelling (4/6) — Percentile reference lines + labeled annotations create solid storytelling; a light IQR shading (Q1–Q3) or a horizontal median line with distinct styling would add a clearer focal point

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct ECDF using p.step(mode='after') — step-after matches 1/n jump at each observation
  • SC-02: Required Features (4/4) — Step function 1/n increments, y-axis 0–1 (1.02 padding), distinct line style, y-grid for percentile reading — all present
  • SC-03: Data Mapping (3/3) — X = finish times, Y = cumulative proportion 0–1, all 300 points shown
  • SC-04: Title & Legend (3/3) — Title includes "ecdf-basic · bokeh · anyplot.ai" with descriptive prefix; no legend for single series (correct)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows ECDF S-curve, step function character, percentile reading — all key aspects visualized
  • DQ-02: Realistic Context (5/5) — Marathon finish times for recreational runners — real, neutral, comprehensible domain
  • DQ-03: Appropriate Scale (4/4) — normal(loc=240, scale=32) min — ~4 hours mean with 32 min std is realistic for recreational marathon finishers

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → tokens → data → ECDF calc → figure → style → save; no functions or classes
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set
  • CQ-03: Clean Imports (2/2) — All imported symbols used (export_png, output_file, save, ColumnDataSource, HoverTool, Label, Span, figure)
  • CQ-04: Code Elegance (2/2) — Loop for percentile reference lines is clean; no over-engineering or fake functionality
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html; current Bokeh API

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — ColumnDataSource, p.step(mode='after'), add_layout(Span), add_layout(Label), HoverTool with renderers — idiomatic Bokeh patterns used correctly
  • LM-02: Distinctive Features (3/5) — HoverTool mode='vline' and Span/Label annotations are distinctly Bokeh; could further leverage CrosshairTool or Band annotation for richer interactivity/shading

Score Caps Applied

  • None — no caps triggered (DE-01=4 and DE-02=3, so the "generic + no refinement" cap does not apply)

Strengths

  • Correct ECDF implementation with p.step(mode='after') — step-after mode precisely matches the 1/n jump at each observation
  • Full theme adaptation: PAGE_BG, INK, INK_SOFT tokens applied to all chrome elements in both renders — no dark-on-dark or light-on-light failures
  • Excellent percentile storytelling: 25th/50th/75th reference lines with labeled annotations enable direct quantile reading
  • Perfect spec compliance across all dimensions; realistic, neutral marathon domain

Weaknesses

  • DE-01 (4/8): Aesthetically correct but generic — needs a design element that elevates it beyond defaults (e.g., subtle area fill under curve, bolder title typography, or refined spacing)
  • DE-02 (3/6): Add explicit min_border padding for generous whitespace; consider setting p.min_border_left = 120 and similar
  • VQ-02 minor: 50th and 75th percentile labels may crowd at ~18 min separation — stagger y-positions (e.g., y=0.08 for the 75th label) to eliminate overlap risk
  • DE-03: A light shaded band (Bokeh Band annotation) between Q1 and Q3 would add a visual focal point and strengthen the distribution-spread story

Issues Found

  1. DE-01 LOW (4/8): Design is a well-configured default, not exceptional
    • Fix: Add a subtle fill_alpha=0.08 area fill under the ECDF curve using p.varea() or shade the IQR band with Bokeh's Band annotation to create visual depth
  2. DE-02 MODERATE (3/6): Missing generous whitespace padding
    • Fix: Set p.min_border_left = 120, p.min_border_bottom = 80, p.min_border_top = 60 for breathing room
  3. VQ-02 MINOR: 50th/75th label crowding risk
    • Fix: Stagger y-positions — e.g., y=0.03 for 25th, y=0.08 for 50th, y=0.03 for 75th (alternating)
  4. DE-03 MODERATE (4/6): Good percentile lines but no visual focal point for distribution spread
    • Fix: Add Band annotation shading between Q1 and Q3 at low alpha (0.10) to immediately communicate spread

AI Feedback for Next Attempt

This is a strong technical implementation (87/100) — all spec requirements met, perfect code quality, correct theme adaptation. The gap to 90+ is entirely in Design Excellence (11/20). To reach APPROVED: (1) add a subtle area fill or Band annotation under/between the ECDF for visual depth (DE-01), (2) increase min_border padding for generous whitespace (DE-02), (3) stagger the 50th/75th percentile label y-positions to eliminate crowding risk. Keep all the correct elements: step mode, HoverTool, Span/Label annotations, and brand green (#009E73).

Verdict: REJECTED

@github-actions github-actions Bot added quality:87 Quality score 87/100 ai-approved Quality OK, ready for merge labels Apr 24, 2026
@github-actions github-actions Bot merged commit 6e72d6a into main Apr 24, 2026
3 checks passed
@github-actions github-actions Bot deleted the implementation/ecdf-basic/bokeh branch April 24, 2026 13:33
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:78 Quality score 78/100 quality:87 Quality score 87/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants