Skip to content

feat(altair): implement bar-race-animated#7323

Merged
MarkusNeusinger merged 4 commits into
mainfrom
implementation/bar-race-animated/altair
May 19, 2026
Merged

feat(altair): implement bar-race-animated#7323
MarkusNeusinger merged 4 commits into
mainfrom
implementation/bar-race-animated/altair

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: bar-race-animated - python/altair

Implements the python/altair version of bar-race-animated.

File: plots/bar-race-animated/implementations/python/altair.py

Parent Issue: #3653


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 19, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot shows a 4-panel small multiples horizontal bar chart on a warm off-white background (#FAF8F1). Each panel represents a key year (2015, 2018, 2021, 2024) with 10 horizontal bars sorted by subscriber count (descending). Bars use the Okabe-Ito palette starting with #009E73 (StreamFlix, green), followed by vermillion (ViewMax), blue (PlayNow), reddish purple (WatchHub), orange (MediaGo), sky blue (CineCloud), yellow (ShowTime), deep indigo (PrimeView), deep green (FlixBox), and deep crimson (CloudTV). Platform names appear to the right of each bar in dark ink, value labels appear in white inside each bar, and year facet headers are displayed prominently above each panel. A legend sits to the right. All text is clearly readable against the warm off-white background. Legibility verdict: PASS.

Dark render (plot-dark.png): The same 4-panel layout appears on a near-black background (#1A1A17). Title, subtitle, and facet year headers render in light text (#F0EFE8). Platform name labels outside bars use theme-adaptive INK (#F0EFE8 in dark mode) — light text against the dark background. Value labels inside bars remain white. The legend uses elevated dark fill (#242420). Data bar colors are identical to the light render — #009E73 for StreamFlix, #D55E00 for ViewMax, etc. — only chrome elements flip. No dark-on-dark failures detected. All text is readable against the dark background. Legibility verdict: PASS.

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

Score: 85/100

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

Visual Quality (26/30)

  • VQ-01: Text Legibility (6/8) — Font sizes explicitly set throughout. Title 34px, subtitle 22px, column headers 26px, axis title 20px, value labels 16px. Platform name labels at 14px fall below the 18px recommended minimum for pixel-based libraries.
  • VQ-02: No Overlap (5/6) — Minor overlap risk only in 2015 panel where very short bars (FlixBox=9, PrimeView=5) push value labels near the bar edge. No meaningful overlap elsewhere.
  • VQ-03: Element Visibility (6/6) — All bars clearly visible; height=45 with corner radius provides good definition. Colors well-differentiated across 10 platforms.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito palette is CVD-safe. Categories distinguishable without relying on hue alone.
  • VQ-05: Layout & Canvas (3/4) — 4-panel facet fills canvas well. Slightly compressed vertically with 10 bars per panel but all elements remain readable.
  • VQ-06: Axis Labels & Title (2/2) — X-axis labeled "Subscribers (millions)" with units. Y-axis hidden (appropriate for bar race). Subtitle provides full context.
  • VQ-07: Palette Compliance (2/2) — First series (#009E73, StreamFlix) correct. Remaining platforms follow Okabe-Ito order. Backgrounds #FAF8F1 / #1A1A17 correct. Chrome fully theme-adaptive in both renders.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above a generic default: corner radius (cornerRadiusEnd=6), custom domain/range palette mapping, legend cornerRadius=4, informative subtitle, large facet headers. Not yet at "strong design" level — no visual hierarchy drawing the eye to key performers or notable transitions.
  • DE-02: Visual Refinement (4/6) — Y-axis hidden, view border removed (strokeWidth=0), subtle grid at 20-25% opacity, facet spacing=20. Refinement is visible but grid could be lighter or omitted entirely for a cleaner look.
  • DE-03: Data Storytelling (3/6) — The 4-year snapshot format tells a temporal story (viewer can track PlayNow rising from Add Claude Code GitHub Workflow #3 to Add workflow diagram for new prototype discovery #1, PrimeView climbing from last to mid-pack). However, no visual emphasis guides the viewer — all bars carry equal weight with no highlight for biggest movers or key transitions.

Spec Compliance (14/15)

  • SC-01: Plot Type (4/5) — Horizontal bar chart with ranked time-ordered snapshots is the correct static fallback approach; the spec explicitly allows small multiples for libraries without animation support. True animation is technically possible in Vega-Lite but is significantly more complex.
  • SC-02: Required Features (4/4) — Bars sorted by value at each time step; entity labels attached to bars; year as visible time indicator (facet headers); color consistent per entity across all panels; tooltips present.
  • SC-03: Data Mapping (3/3) — X = Subscribers (value driving bar length and ranking), Y = Rank (sorted descending), Color = Platform.
  • SC-04: Title & Legend (3/3) — Title is exactly bar-race-animated · python · altair · anyplot.ai. Legend labels match platform names. Subtitle adds descriptive context.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows ranking changes over time, growth trajectories, platform overtakes. The animation aspect (smooth transitions) is approximated by 4 snapshots; captures major shifts but misses intermediate dynamics.
  • DQ-02: Realistic Context (5/5) — Fictional streaming platform names in a neutral business scenario. Avoids real-company controversies while remaining immediately recognizable as a domain.
  • DQ-03: Appropriate Scale (4/4) — Subscribers range from ~5M (PrimeView 2015) to ~203M (PlayNow 2024). Annual growth rates of 5-30% are realistic for the streaming industry.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear flow: imports -> theme tokens -> palette -> data -> chart layers -> facet -> save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set before data generation.
  • CQ-03: Clean Imports (2/2) — Only os, altair, numpy, pandas imported; all used.
  • CQ-04: Code Elegance (2/2) — Layer composition (bar_chart + text_labels + value_labels) is clean and idiomatic. resolve_scale(x='independent') is the correct approach for per-facet x-scale independence.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png (scale_factor=3.0) and plot-{THEME}.html. Correct file naming convention.

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Layer composition with + operator, .facet() for small multiples, configure_*() for theme, alt.Scale(domain=..., range=...) for explicit palette, encoding type suffixes — all idiomatic Altair patterns used correctly.
  • LM-02: Distinctive Features (4/5) — resolve_scale(x='independent') for per-facet independent axes is a genuinely Altair/Vega-Lite-specific pattern. Layer composition and declarative faceting are distinctive to the Grammar of Graphics approach. Falls short of full marks only because Vega-Lite animation (the most distinctive differentiator for this chart type) was not attempted.

Score Caps Applied

  • None — DE-01=5 and DE-02=4; neither pair meets both-<=2 threshold for the 75-point cap. No other caps triggered.

Strengths

  • Perfect code quality: clean KISS structure, seed set, all imports used, idiomatic Altair layer composition and faceting
  • Correct Okabe-Ito palette with explicit domain/range mapping ensuring consistent colors across all time panels
  • Full theme-adaptive chrome in both renders — no dark-on-dark or light-on-light failures detected
  • resolve_scale(x='independent') correctly handles the dramatically different value ranges across years (5M in 2015 vs 203M in 2024)
  • HTML output saved alongside PNG, providing interactivity (tooltips) even in the static fallback approach

Weaknesses

  • Platform name labels at fontSize=14 fall below the 18px minimum for pixel-based libraries — raise to 16-18px
  • No visual emphasis to highlight key storylines (biggest movers, Add workflow diagram for new prototype discovery #1 ranked bar per panel) — all bars carry equal visual weight
  • Grid at 20-25% opacity is slightly prominent; reducing to 10-15% or removing entirely for a cleaner look relying on value labels
  • DE-03 limited: rank numbers on bars or a subtle highlight for the top-ranked platform per panel would guide the viewer to the core narrative

Issues Found

  1. DE-03 LOW (3/6): No visual emphasis on key data points or transitions. All bars are treated equally — the viewer must find the story themselves.
  2. DE-01 MODERATE (5/8): Design is above generic defaults but lacks a strong visual signature.
    • Fix: Remove the x-axis grid entirely (value labels already encode exact numbers), add rank numbers (1-10) at the left of each row, or apply a light background band to visually separate the top 3
  3. VQ-01 MINOR (6/8): Platform name labels at fontSize=14 are below the 18px minimum.
    • Fix: Raise fontSize to 17 or 18

AI Feedback for Next Attempt

The technical foundation is strong — code quality and library usage are both excellent. Focus the next attempt on design storytelling and visual refinement: (1) raise platform name labels from fontSize=14 to 17-18, (2) highlight the #1-ranked bar per panel using bold text weight or a subtle elongated background, (3) reduce x-axis grid opacity to 10-15% or remove the grid entirely since value labels already provide exact numbers, and (4) add rank position numbers (1-10) at the left edge of each row to make ranking explicit. These targeted changes would push DE-01 from 5 to 6, DE-02 from 4 to 5, and DE-03 from 3 to 4, bringing the total to approximately 90.

Verdict: REJECTED

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

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Four-panel small-multiples layout on a warm off-white #FAF8F1 background, showing key snapshots for 2015, 2018, 2021, and 2024. Horizontal bars are coloured using the Okabe-Ito palette starting with #009E73 (StreamFlix). Each bar carries a white value label (subscriber count) inside and a bold dark platform-name label just beyond the bar end. Year column headers are large (26px) and clearly readable. X-axis is titled "Subscribers (millions)" with unit-labelled tick marks. A Platform legend with all 10 entries sits at the right. Independent x-scales correctly widen each year facet to its own data range, preventing 2015 bars from being compressed against the 2024 maximum. All text is clearly readable against the warm off-white background — no light-on-light issues.

Dark render (plot-dark.png): Identical composition on a near-black #1A1A17 background. Title, subtitle, year headers, axis labels, tick labels, and legend text all render in the light INK token (#F0EFE8 / #B8B7B0) — no dark-on-dark failures detected. Bar colours are identical to the light render: Okabe-Ito palette is theme-independent and all 10 hues carry across unchanged. White value labels inside bars remain legible on coloured bars. Platform-name labels outside bars use the INK token which correctly resolves to the light value in dark mode. All text readable; both renders pass the legibility check.

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

Score: 89/100

Category Score Max
Visual Quality 29 30
Design Excellence 12 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 8 10
Total 89 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — Most sizes explicitly set (title 34px, subtitle 22px, year headers 26px, axis title 20px, axis labels 16px, legend 16–18px). text_labels layer at 14px is marginally below the 16px minimum but readable at scale_factor=3.0 output.
  • VQ-02: No Overlap (6/6) — Clean faceted layout; bar labels and value labels well separated.
  • VQ-03: Element Visibility (6/6) — Bars at height=45 clearly visible; cornerRadiusEnd adds definition; colours well differentiated.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito is CVD-safe; adequate contrast between bars and backgrounds.
  • VQ-05: Layout & Canvas (4/4) — Four-panel facet fills canvas well; legend to the right; balanced margins.
  • VQ-06: Axis Labels & Title (2/2) — X-axis titled "Subscribers (millions)" with units; Y-axis correctly omitted (ranks labelled on bars).
  • VQ-07: Palette Compliance (2/2) — First series #009E73; Okabe-Ito order with accessible extensions for positions 8–10. Backgrounds #FAF8F1 / #1A1A17. Chrome fully theme-adaptive in both renders.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Clearly above defaults: rounded corners, multi-layer labels, clean faceting. Falls short of strong-design (6) — no standout emphasis or focal-point technique.
  • DE-02: Visual Refinement (4/6) — Hidden Y-axis, no view borders, subtle grid, facet spacing, legend padding/cornerRadius. Minor: grid opacity mismatch (0.25 encoding vs 0.20 configure_axis).
  • DE-03: Data Storytelling (3/6) — Time-progression story visible across 4 years with rank ordering. Rank-change narrative (PlayNow rise) is present but not visually emphasised.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct small-multiples implementation for a library without native animation support, as explicitly permitted by spec.
  • SC-02: Required Features (4/4) — Bars sorted by value at each snapshot; entity labels on bars; visible time indicator (year headers); colour consistent per entity across all frames.
  • SC-03: Data Mapping (3/3) — X = Subscribers, Y = Rank (ordinal, descending). All 10 platforms across 4 years.
  • SC-04: Title & Legend (3/3) — Title: bar-race-animated · python · altair · anyplot.ai — exact format. Subtitle descriptive. Legend labels match all 10 platforms.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all aspects: rank ordering, value-driven bar length, time progression, colour coding, diverse growth trajectories.
  • DQ-02: Realistic Context (5/5) — Streaming platform subscribers (millions) — realistic, neutral, business domain. Fictional platform names are plausible.
  • DQ-03: Appropriate Scale (4/4) — 2015 base 5–40M plausible for early streaming; 2024 range 10–200M reflects realistic decade-long growth.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear flow: imports → tokens → data → chart layers → facet → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) before synthetic data generation.
  • CQ-03: Clean Imports (2/2) — os, altair, numpy, pandas — all used.
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic Altair composition; no over-engineering.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png (scale_factor=3.0) and plot-{THEME}.html. Current Altair 6.1.0 API.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) — Expert use of Altair high-level API: mark_bar, encoding types (Q/N/O), layer composition (+), facet(), configure_* chain, resolve_scale.
  • LM-02: Distinctive Features (3/5) — Uses Altair-distinctive features: facet(column=...), layer composition (bar + text + value), resolve_scale(x='independent'). No use of params/selection which would further differentiate from other libraries.

Score Caps Applied

  • None — all category scores above cap thresholds.

Strengths

  • Clean small-multiples design with four key-year facets clearly showing ranking progression over time
  • Triple-layer Altair composition (bars + value labels + platform name labels) adds data richness without clutter
  • Correct Okabe-Ito palette with #009E73 as first series, plus accessible extensions for 10 entities
  • Full theme-adaptive chrome: backgrounds, text, grid, and legend all correctly flip between light and dark
  • Independent x-axis scales per facet (resolve_scale) let each year use its own range
  • Rounded bar corners and hidden Y-axis give a polished, modern look
  • Clean KISS code structure with reproducibility seed and all font sizes explicitly set

Weaknesses

  • DE-01 (5/8): Lacks a standout design flourish — e.g., a callout annotation on the rank-1 crossover year, or a bold highlight on the platform that overtook the leader
  • DE-03 (3/6): The rank-change story (PlayNow rising from Add Claude Code GitHub Workflow #3 to Add workflow diagram for new prototype discovery #1) is visible but not emphasised; a rank-delta annotation or bolder colour contrast on the biggest mover would guide the viewer's eye
  • DE-02 (4/6): Grid opacity 0.25 (encoding-level) overrides the configure_axis value of 0.20; unifying to ≤0.15 would produce a subtler grid
  • LM-02 (3/5): Altair's params/selection-driven interactivity is not used; even a step-slider param would demonstrate a more distinctive Altair capability

Issues Found

  1. DE-01/DE-03 MODERATE: No visual emphasis on the most interesting rank changes across the four snapshots — the plot displays data correctly but doesn't guide the viewer to the story
    • Fix: Add a subtle rank-delta annotation (e.g., "↑4" next to the biggest mover) or use a slightly bolder/brighter bar for the current rank-1 entity to create a focal point

AI Feedback for Next Attempt

This is a solid, well-executed implementation that clears the attempt-2 threshold (89 ≥ 80). If regenerated, focus improvements on: (1) a focal-point technique to highlight the biggest rank-change story — even a small annotation or opacity contrast on the leader bar per year would lift DE-03 from 3 to 5; (2) unify grid opacity to ≤0.15 throughout; (3) consider Altair params with a year step-selector for interactivity to lift LM-02.

Verdict: APPROVED

@github-actions github-actions Bot added quality:89 Quality score 89/100 ai-approved Quality OK, ready for merge and removed quality:85 Quality score 85/100 labels May 19, 2026
@MarkusNeusinger MarkusNeusinger merged commit 1f22955 into main May 19, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/bar-race-animated/altair branch May 19, 2026 02:18
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:89 Quality score 89/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant