Skip to content

feat(altair): implement stem-basic#5631

Merged
MarkusNeusinger merged 5 commits into
mainfrom
implementation/stem-basic/altair
Apr 30, 2026
Merged

feat(altair): implement stem-basic#5631
MarkusNeusinger merged 5 commits into
mainfrom
implementation/stem-basic/altair

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: stem-basic - python/altair

Implements the python/altair version of stem-basic.

File: plots/stem-basic/implementations/python/altair.py

Parent Issue: #972


🤖 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): Warm off-white background (#FAF8F1) — correct, not pure white. Title "stem-basic · altair · anyplot.ai" is bold, dark, and clearly readable. X-axis label "Sample Index (n)" and Y-axis label "Amplitude (a.u.)" are both dark-inked and well-sized. Tick labels (0–29 on x-axis, −0.6 to 1.2 on y-axis) are rendered in dark text and clearly readable. The 30 stems appear in brand green #009E73 with circular markers at their tips; a horizontal baseline rule sits at y=0 in soft ink. The data shows a damped oscillation with exponential decay — both positive (up to ~1.0) and negative (down to ~−0.6) values are visible. All text is readable against the light background.

Dark render (plot-dark.png): Near-black background (#1A1A17) — correct, warm near-black not pure black. Title and axis labels appear in light-colored text, clearly readable. Tick labels are light-colored and clearly legible — no dark-on-dark issues detected. Data stems and markers remain identical brand green #009E73 (unchanged from the light render, as expected). The baseline rule is visible in an appropriate soft-ink color. Brand green #009E73 reads well on the dark surface. All text is readable against the dark background.

Both paragraphs confirmed. No legibility failures in either theme.

Score: 89/100

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

Visual Quality (30/30)

  • VQ-01: Text Legibility (8/8) — All font sizes explicitly set: title 28px, axis labels 22px, tick labels 18px; readable in both themes
  • VQ-02: No Overlap (6/6) — 30 evenly spaced stems, no tick label or element overlap
  • VQ-03: Element Visibility (6/6) — Markers size=300 with stroke ring for contrast, stems strokeWidth=2.5 opacity=0.85 — all clearly visible
  • VQ-04: Color Accessibility (2/2) — Single brand green series, CVD-safe Okabe-Ito position 1
  • VQ-05: Layout & Canvas (4/4) — 1600×900 at scale_factor=3.0 = 4800×2700px, balanced margins, good canvas utilization
  • VQ-06: Axis Labels & Title (2/2) — X: "Sample Index (n)", Y: "Amplitude (a.u.)" — descriptive with units
  • VQ-07: Palette Compliance (2/2) — First/only series #009E73; light bg #FAF8F1, dark bg #1A1A17; full theme-adaptive chrome applied correctly

Design Excellence (10/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above generic default (brand color, marker stroke rings, careful theme tokens) but not publication-level; no typographic hierarchy or color variation beyond the single brand green
  • DE-02: Visual Refinement (3/6) — Grid opacity explicitly set to 0.10 (subtle), but full 4-sided view border box is present (style guide: remove top/right spines); grid appears on both axes (Y-only would be cleaner for a discrete-point plot)
  • DE-03: Data Storytelling (2/6) — Damped oscillation data inherently tells a story, but no visual design element emphasizes it — no decay envelope, color gradient along the decay, or annotation highlighting the signal behavior

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct: mark_rule (stems) + mark_circle (markers) + baseline rule at y=0
  • SC-02: Required Features (4/4) — Thin stems (strokeWidth=2.5), visible circular markers at tips, baseline at y=0, consistent sizing throughout
  • SC-03: Data Mapping (3/3) — X=sample index, Y=amplitude; all 30 points visible with correct stem heights
  • SC-04: Title & Legend (3/3) — Title "stem-basic · altair · anyplot.ai" exactly matches format; single series, no legend required (N/A)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all stem plot aspects: positive and negative values, large height variation, clear exponential decay pattern
  • DQ-02: Realistic Context (5/5) — Acoustic impulse response samples: real-world signal processing context, neutral and physically plausible
  • DQ-03: Appropriate Scale (4/4) — Amplitude ~±1 a.u., decay constant 1/8, 30 samples — all plausible for an acoustic impulse response

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → theme tokens → data → plot layers → compose → save
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set
  • CQ-03: Clean Imports (2/2) — os, altair, numpy, pandas — all used
  • CQ-04: Code Elegance (2/2) — Clean Pythonic code, idiomatic layer composition, no fake functionality
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png (scale_factor=3.0) and plot-{THEME}.html; current Altair API

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Excellent: mark_rule with y2 encoding for stems, layer composition with + operator, configure_* for global styling — all canonical Altair patterns
  • LM-02: Distinctive Features (4/5) — Layer composition (baseline + stems + markers) and y2 span encoding are distinctly Altair grammar-of-graphics features; tooltip configuration adds HTML interactivity

Score Caps Applied

  • None — No caps triggered (VQ-02=6, VQ-03=6, SC-01=5, DQ-02=5, DE-01=5 > 2, CQ-04=2 > 0)

Strengths

  • Perfect visual quality (30/30): all font sizes explicitly set, no overlap, markers with stroke rings for definition, correct Okabe-Ito brand green throughout both themes
  • Idiomatic Altair stem plot using mark_rule (y→y2 span) + mark_circle layer composition — the right way to build this in Altair
  • Full theme-adaptive chrome: correct warm backgrounds (#FAF8F1 light / #1A1A17 dark), light and dark text correctly applied, no legibility failures in either render
  • Realistic acoustic impulse response data showing full stem plot feature coverage: positive/negative values, exponential decay, oscillation

Weaknesses

  • Full 4-sided view border box (configure_view stroke=INK_SOFT): the style guide requires removing top/right spines — use configure_view(stroke=None) and control domain lines via configure_axis(domain=True) on left/bottom only, or remove the view stroke entirely
  • Both-axis grid: for a discrete-point stem plot, a Y-axis-only grid or no grid would be cleaner; horizontal grid lines compete with the vertical stems
  • No visual emphasis on the story: the exponential decay is the data's insight, but no design element guides the eye — consider a subtle decay envelope line or area shading to highlight the decaying amplitude pattern

Issues Found

  1. DE-02 MEDIUM: Full box border + dual-axis grid reduce visual refinement
    • Fix: Set configure_view(stroke=None) to remove the box border; configure only Y-axis grid or disable grid entirely (gridOpacity=0 or grid=False in configure_axis)
  2. DE-03 LOW: No visual hierarchy or storytelling emphasis
    • Fix: Add a subtle decay envelope (e.g., a dashed line showing exp(-n/8) and its negative) to frame the signal attenuation, or use an area layer with low opacity behind the stems to suggest the envelope

AI Feedback for Next Attempt

Remove the view border box (configure_view(stroke=None)) and switch to Y-axis-only or no grid for cleaner visual refinement. Add a visual element that tells the decay story — a dashed decay envelope line (exp(-x/8) and its negative) or a shaded area behind the stems would elevate DE-02 and DE-03 significantly. The technical implementation is excellent; the gap is in visual polish and storytelling.

Verdict: REJECTED

@github-actions github-actions Bot added quality:89 Quality score 89/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): Warm off-white #FAF8F1 background — correctly rendered, not pure white. Title "stem-basic · altair · anyplot.ai" centered at top in dark ink, clearly readable. Y-axis label "Amplitude (a.u.)" and X-axis label "Sample Index (n)" both in dark ink with units. Tick labels in INK_SOFT gray, readable. 30 green (#009E73) stems extend from baseline (y=0) to oscillating amplitude values; circular markers at each tip with PAGE_BG-colored stroke for crisp edges. Shaded teal envelope spanning ±exp(-n/8) decay bounds with dashed gray boundary lines adds strong visual narrative. Horizontal gridlines are subtle (opacity 0.10); X-axis has no grid. All text is clearly readable against the light background — no light-on-light issues.

Dark render (plot-dark.png): Warm near-black #1A1A17 background — correctly rendered, not pure black. Title and axis labels appear in light #F0EFE8 ink; tick labels in #B8B7B0 light gray — both clearly readable against the dark surface. No dark-on-dark failures observed. Data colors are identical to the light render — stems and markers remain #009E73 brand green, confirming only chrome flipped. Shaded decay envelope reads as slightly deeper teal against the dark background but the envelope bounds remain visible as lighter gray dashed lines. Brand green #009E73 reads well in dark mode. All text legible; both renders pass theme-readability check.

Both paragraphs confirmed — review is valid.

Score: 89/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title 28px, axis 22px, ticks 18px); readable in both themes; minor deduction as title fontWeight not bolded
  • VQ-02: No Overlap (6/6) — No overlapping text or elements
  • VQ-03: Element Visibility (6/6) — Markers size=300 appropriate for 30 points; stems strokeWidth=2.5 clearly visible
  • VQ-04: Color Accessibility (2/2) — Single CVD-safe Okabe-Ito green; high contrast on both backgrounds
  • VQ-05: Layout & Canvas (4/4) — 1600×900 × scale_factor=3 = 4800×2700; good canvas utilization
  • VQ-06: Axis Labels & Title (2/2) — "Sample Index (n)" and "Amplitude (a.u.)" with units
  • VQ-07: Palette Compliance (2/2) — First series #009E73; backgrounds #FAF8F1/#1A1A17; all chrome theme-adaptive

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (5/8) — Decay envelope overlay shows design intent clearly above library defaults; clean single-color story; above default (4) but monochromatic palette limits the ceiling
  • DE-02: Visual Refinement (4/6) — X-grid off, y-grid gridOpacity=0.10, configure_view(stroke=None); good refinement but horizontal gridlines still run full-width and are noticeable on the sparse stem chart
  • DE-03: Data Storytelling (5/6) — Shaded decay envelope with dashed ±exp(-n/8) bounds creates a strong, immediately legible narrative about signal attenuation; viewer focus is guided naturally

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct stem plot: mark_rule (y/y2) for stems + mark_circle for markers
  • SC-02: Required Features (4/4) — Stems, markers, baseline at y=0, consistent sizing throughout
  • SC-03: Data Mapping (3/3) — X = sample index, Y = amplitude; all 30 data points visible
  • SC-04: Title & Legend (3/3) — stem-basic · altair · anyplot.ai; no legend (correct for single series)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows positive and negative values, damped oscillation, decaying envelope — full range of stem plot features
  • DQ-02: Realistic Context (5/5) — Acoustic impulse response is a canonical, neutral real-world stem plot use case
  • DQ-03: Appropriate Scale (4/4) — 30 samples (within 10–100 spec range); amplitude ±1 appropriate for normalized signal

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — No functions or classes; linear flow: tokens → data → charts → compose → save
  • CQ-02: Reproducibility (2/2) — np.random.seed(42)
  • CQ-03: Clean Imports (2/2) — os, altair, numpy, pandas — all used
  • CQ-04: Code Elegance (2/2) — Clean layer composition; appropriate complexity for envelope + stems
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — Y2 encoding for vertical rules is idiomatic Altair; configure_axis/configure_view/configure_title properly used; configure_axisX(grid=False) for fine-grained control
  • LM-02: Distinctive Features (2/5) — Layer composition (+) and Y2 encoding are Altair-distinctive; HTML export and tooltip formatting are present; however, the implementation does not leverage Altair's selections, parameter bindings, transforms, or other uniquely powerful declarative features

Score Caps Applied

  • None

Strengths

  • Decay envelope overlay (shaded area + dashed bounds) adds meaningful visual context that tells the exponential decay story — a thoughtful addition beyond the spec minimum
  • Full theme-adaptive chrome: PAGE_BG, INK, INK_SOFT tokens correctly applied in both renders with no dark-on-dark or light-on-light failures
  • Perfect spec compliance: mark_rule (y/y2) for stems, mark_circle for markers, baseline rule, correct title format
  • Font sizes explicitly set to spec values; readable at full 4800×2700 resolution in both themes
  • Clean Altair layer composition using + operator; marker stroke set to PAGE_BG for crisp definition

Weaknesses

  • LM-02 low: does not leverage Altair-distinctive features like selections, parameter bindings, or transforms; HTML export is present but the interactive potential is underutilized (tooltips exist but no hover highlighting or linked views)
  • DE-01 could go higher with bolded title (fontWeight='bold') and slightly stronger typography hierarchy to push into strong-design territory
  • DE-02: horizontal gridlines still noticeable on a sparse discrete plot; removing them entirely (gridOpacity=0) would improve visual refinement for this chart type

Issues Found

  1. LM-02 BELOW DEFAULT: Only basic layer composition and Y2 encoding distinguish this from other libraries; interactive HTML output exists but offers no Altair-native interactivity features
    • Fix: Add a selection/parameter for hover highlighting, or use alt.condition for emphasis based on a hover selection
  2. DE-02 REFINEMENT: Horizontal gridlines run full-width and are visible even at 10% opacity on a sparse 30-point discrete chart
    • Fix: Set gridOpacity=0 on configure_axisY, or reduce to 0.06, for cleaner look

AI Feedback for Next Attempt

The implementation is high quality and above the approval threshold. Key remaining improvements: (1) add Altair-specific interactivity to LM-02 — even a simple alt.selection_point() on hover with alt.condition to highlight the nearest stem would demonstrate library mastery; (2) optionally set title=alt.Title(..., fontWeight='bold') for stronger title hierarchy; (3) consider removing y-gridlines entirely (gridOpacity=0) on this sparse discrete chart for maximum refinement.

Verdict: APPROVED

@github-actions github-actions Bot added the ai-approved Quality OK, ready for merge label Apr 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit 7ad1f85 into main Apr 30, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/stem-basic/altair branch April 30, 2026 15: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:89 Quality score 89/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant