Skip to content

feat(altair): implement ecdf-basic#9488

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/ecdf-basic/altair
Jun 25, 2026
Merged

feat(altair): implement ecdf-basic#9488
MarkusNeusinger merged 6 commits into
mainfrom
implementation/ecdf-basic/altair

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: ecdf-basic - python/altair

Implements the python/altair version of ecdf-basic.

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

Parent Issue: #976


🤖 impl-generate workflow

github-actions Bot added 2 commits June 25, 2026 09:38
Regen from quality 86. Addressed:
- Added dashed reference lines at Q1/median/Q3 with focal markers (DE-03: no focal point)
- Y-axis-only grid via configure_axisX(grid=False) (style guide prefers Y-only for line charts)
- Fixed canvas to canonical width=620/height=320/scale_factor=4.0 with PIL padding to 3200×1800
- Added "python" language token to title (ecdf-basic · python · altair · anyplot.ai)
- Normalised font sizes to canonical altair values (title 16px, axis 12px, ticks 10px)
- Added sys.path fix so altair.py doesn't shadow the altair library on import
@claude

claude Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): ECDF step-after line plot on a warm off-white (#FAF8F1) background. The brand green (#009E73) step function rises from ~20ms to ~260ms on the X-axis ('API Response Time (ms)') with the Y-axis ('Cumulative Proportion') formatted as percentages from 0% to 100%. Three focal marker points (filled green circles) sit at the Q1 (~97ms / 25%), median (~122ms / 50%), and Q3 (~140ms / 75%) intersections. Dashed gray reference lines span both axes at these three quartiles, forming crosshairs. Title 'ecdf-basic · python · altair · anyplot.ai' in dark ink is clearly visible. Axis labels, tick labels, and all text are readable against the light background. Horizontal grid lines at 10% opacity are subtle but present. No text overflow or clipping observed.
Legibility verdict: PASS

Dark render (plot-dark.png): Identical layout on a warm near-black (#1A1A17) background. Title appears in light/near-white text, fully readable. Axis labels 'API Response Time (ms)' and 'Cumulative Proportion' are light-colored and clearly legible. Tick labels are light gray against the dark surface — no dark-on-dark failures. Brand green ECDF line and focal markers are identical in color (#009E73) to the light render; only chrome (background, text, grid) flips. Reference lines are visible in muted gray. No clipping, no text overlaps.
Legibility verdict: PASS — data colors identical between both renders; no dark-on-dark issues.

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) — fontSize=16 title, 12 axis labels, 10 ticks; all readable at full resolution in both themes. Proportions well balanced.
  • VQ-02: No Overlap (6/6) — no text or data collisions in either render
  • VQ-03: Element Visibility (6/6) — strokeWidth=3.5 ECDF line appropriate for 250-point medium-density data; focal markers clearly visible
  • VQ-04: Color Accessibility (2/2) — single series brand green CVD-safe; dashed reference lines in theme-adaptive muted gray
  • VQ-05: Layout & Canvas (4/4) — canvas gate passed; padding to exact 3200×1800 via PIL; no overflow or clipping
  • VQ-06: Axis Labels & Title (2/2) — 'API Response Time (ms)' and 'Cumulative Proportion' are descriptive with units
  • VQ-07: Palette Compliance (2/2) — first (only) series uses #009E73; backgrounds #FAF8F1/#1A1A17 correct; all chrome theme-adaptive

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — intentional quartile focal points with crosshair reference lines create meaningful visual hierarchy above defaults; no text annotations on markers limits expressiveness
  • DE-02: Visual Refinement (3/6) — X-axis grid disabled, Y-axis-only horizontal grid at 10% opacity is pleasingly subtle; configure_view strokeWidth=0 removes frame border; good whitespace
  • DE-03: Data Storytelling (4/6) — Q1/median/Q3 crosshairs guide the viewer to read exact percentiles; real-world API latency context grounded; interactive tooltips add discovery layer

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — step-after ECDF using mark_line(interpolate='step-after'); correct chart type
  • SC-02: Required Features (4/4) — 1/n step increments; Y-axis domain [0,1]; distinct line style; grid lines for reading percentile values
  • SC-03: Data Mapping (3/3) — X=latency_ms, Y=cumulative proportion; all 250 observations mapped; Y-axis percentage format readable
  • SC-04: Title & Legend (3/3) — 'ecdf-basic · python · altair · anyplot.ai' exactly; no legend (single-series, correct omission)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — step function, quartile markers, reference lines, full ECDF shape including tail
  • DQ-02: Realistic Context (5/5) — API response latency from production web service; normal(120ms, 35ms), clipped at 20ms; plausible and neutral
  • DQ-03: Appropriate Scale (4/4) — 20–260ms range realistic; 250 observations ideal for ECDF; 0–100% Y-axis correct

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — no functions/classes; clean procedural script; sys.path fix is necessary and well-commented
  • CQ-02: Reproducibility (2/2) — np.random.seed(42)
  • CQ-03: Clean Imports (2/2) — all imports used (os, sys, altair, numpy, pandas, PIL)
  • CQ-04: Code Elegance (2/2) — clean alt.layer composition; logical data → chart → save → pad flow
  • CQ-05: Output & API (1/1) — saves plot-{THEME}.png and plot-{THEME}.html; no bare plot.png; current API

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) — alt.layer() composition; correct Q/N/T encoding types; configure_* for theming; .interactive() for zoom/pan; mark_line(interpolate='step-after') is the canonical Vega-Lite ECDF approach
  • LM-02: Distinctive Features (3/5) — multi-layer composition (ECDF + h_rules + v_rules + focal_pts) leverages Altair's declarative grammar well; interactive tooltips on two mark types; could be further elevated by using Altair's built-in window transform for cumulative rank calculation instead of manual numpy preprocessing

Score Caps Applied

  • None

Strengths

  • Correct step-after interpolation using native Altair mark_line API — exactly the idiomatic Vega-Lite approach for ECDF
  • Theme-adaptive chrome fully and correctly implemented: PAGE_BG, INK, INK_SOFT, INK_MUTED all wired through configure_axis/configure_title/configure_view
  • Quartile crosshairs (horizontal + vertical dashed rules) with focal green markers enable direct percentile reading without hover
  • Real-world API latency data context is compelling and appropriately scaled
  • Canvas pad-only pattern correctly implemented; PIL raises on overshoot
  • Interactive HTML output with dual-tooltip (line + marker) for both latency and proportion values

Weaknesses

  • Quartile focal markers lack text annotations showing actual values (e.g. '~97ms', '~122ms', '~140ms') — tooltips require hover, losing the at-a-glance reading advantage
  • LM-02 gap: ECDF computed manually in numpy; Altair's window transform ( with + , then for proportion) would compute it declaratively in Vega-Lite, showcasing the library's data transformation capabilities
  • Grid opacity 0.10 is at the low end of the 10–15% style guide range; increasing to 0.13–0.15 would make horizontal guides slightly more useful for reading exact proportions

Issues Found

  1. LM-02 MODERATE: Manual numpy ECDF calculation misses Altair's declarative window transform pattern
    • Fix: Replace numpy sort+arange with + to compute ranks within Vega-Lite
  2. DE-01 MILD: No value labels on quartile focal points — add a text mark layer with formatted latency values near each marker to make key percentiles immediately readable without hover

AI Feedback for Next Attempt

Strong implementation with correct ECDF step-after interpolation, excellent theming, and good design intent. To elevate further: (1) add a text mark layer on the three quartile focal points showing the latency values (e.g. '~97ms', '~122ms', '~140ms') so key percentiles are readable without hover; (2) use Altair's window transform for the ECDF calculation rather than numpy preprocessing to demonstrate library-native data transformation capabilities; (3) increase Y-axis gridOpacity slightly from 0.10 to 0.13 for marginally improved percentile reading.

Verdict: APPROVED

@claude

claude Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): ECDF step-after line plot on a warm off-white (#FAF8F1) background. The brand green (#009E73) step function rises from ~20ms to ~260ms on the X-axis ('API Response Time (ms)') with the Y-axis ('Cumulative Proportion') formatted as percentages from 0% to 100%. Three focal marker points (filled green circles) sit at the Q1 (~97ms / 25%), median (~122ms / 50%), and Q3 (~140ms / 75%) intersections. Dashed gray reference lines span both axes at these three quartiles, forming crosshairs. Title 'ecdf-basic · python · altair · anyplot.ai' in dark ink is clearly visible. Axis labels, tick labels, and all text are readable against the light background. Horizontal grid lines at 10% opacity are subtle but present. No text overflow or clipping observed.
Legibility verdict: PASS

Dark render (plot-dark.png): Identical layout on a warm near-black (#1A1A17) background. Title appears in light/near-white text, fully readable. Axis labels 'API Response Time (ms)' and 'Cumulative Proportion' are light-colored and clearly legible. Tick labels are light gray against the dark surface — no dark-on-dark failures. Brand green ECDF line and focal markers are identical in color (#009E73) to the light render; only chrome (background, text, grid) flips. Reference lines are visible in muted gray. No clipping, no text overlaps.
Legibility verdict: PASS — data colors identical between both renders; no dark-on-dark issues.

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) — fontSize=16 title, 12 axis labels, 10 ticks; all readable at full resolution in both themes. Proportions well balanced.
  • VQ-02: No Overlap (6/6) — no text or data collisions in either render
  • VQ-03: Element Visibility (6/6) — strokeWidth=3.5 ECDF line appropriate for 250-point medium-density data; focal markers clearly visible
  • VQ-04: Color Accessibility (2/2) — single series brand green CVD-safe; dashed reference lines in theme-adaptive muted gray
  • VQ-05: Layout & Canvas (4/4) — canvas gate passed; padding to exact 3200x1800 via PIL; no overflow or clipping
  • VQ-06: Axis Labels & Title (2/2) — 'API Response Time (ms)' and 'Cumulative Proportion' are descriptive with units
  • VQ-07: Palette Compliance (2/2) — first (only) series uses #009E73; backgrounds #FAF8F1/#1A1A17 correct; all chrome theme-adaptive

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — intentional quartile focal points with crosshair reference lines create meaningful visual hierarchy above defaults; no text annotations on markers limits expressiveness
  • DE-02: Visual Refinement (3/6) — X-axis grid disabled, Y-axis-only horizontal grid at 10% opacity is pleasingly subtle; configure_view strokeWidth=0 removes frame border; good whitespace
  • DE-03: Data Storytelling (4/6) — Q1/median/Q3 crosshairs guide the viewer to read exact percentiles; real-world API latency context grounded; interactive tooltips add discovery layer

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — step-after ECDF using mark_line(interpolate='step-after'); correct chart type
  • SC-02: Required Features (4/4) — 1/n step increments; Y-axis domain [0,1]; distinct line style; grid lines for reading percentile values
  • SC-03: Data Mapping (3/3) — X=latency_ms, Y=cumulative proportion; all 250 observations mapped; Y-axis percentage format readable
  • SC-04: Title & Legend (3/3) — 'ecdf-basic · python · altair · anyplot.ai' exactly; no legend (single-series, correct omission)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — step function, quartile markers, reference lines, full ECDF shape including tail
  • DQ-02: Realistic Context (5/5) — API response latency from production web service; normal(120ms, 35ms), clipped at 20ms; plausible and neutral
  • DQ-03: Appropriate Scale (4/4) — 20-260ms range realistic; 250 observations ideal for ECDF; 0-100% Y-axis correct

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — no functions/classes; clean procedural script; sys.path fix is necessary
  • CQ-02: Reproducibility (2/2) — np.random.seed(42)
  • CQ-03: Clean Imports (2/2) — all imports used (os, sys, altair, numpy, pandas, PIL)
  • CQ-04: Code Elegance (2/2) — clean alt.layer composition; logical data → chart → save → pad flow
  • CQ-05: Output & API (1/1) — saves plot-{THEME}.png and plot-{THEME}.html; no bare plot.png; current API

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) — alt.layer() composition; correct Q/N/T encoding types; configure_* for theming; .interactive() for zoom/pan; mark_line(interpolate='step-after') is the canonical Vega-Lite ECDF approach
  • LM-02: Distinctive Features (3/5) — multi-layer composition (ECDF + h_rules + v_rules + focal_pts) leverages Altair's declarative grammar well; interactive tooltips on two mark types; could be further elevated by using Altair's built-in window transform for cumulative rank calculation instead of manual numpy preprocessing

Score Caps Applied

  • None

Strengths

  • Correct step-after interpolation using native Altair mark_line API — exactly the idiomatic Vega-Lite approach for ECDF
  • Theme-adaptive chrome fully and correctly implemented: PAGE_BG, INK, INK_SOFT, INK_MUTED all wired through configure_axis/configure_title/configure_view
  • Quartile crosshairs (horizontal + vertical dashed rules) with focal green markers enable direct percentile reading without hover
  • Real-world API latency data context is compelling and appropriately scaled
  • Canvas pad-only pattern correctly implemented; PIL raises on overshoot
  • Interactive HTML output with dual-tooltip (line + marker) for both latency and proportion values

Weaknesses

  • Quartile focal markers lack text annotations showing actual values (e.g. '~97ms', '~122ms', '~140ms') — tooltips require hover, losing the at-a-glance reading advantage
  • LM-02 gap: ECDF computed manually in numpy; Altair's window transform (transform_window with sort + count(), then transform_calculate for proportion) would compute it declaratively in Vega-Lite, showcasing the library's data transformation capabilities
  • Grid opacity 0.10 is at the low end of the 10-15% style guide range; increasing to 0.13-0.15 would make horizontal guides marginally more useful for reading exact proportions

Issues Found

  1. LM-02 MODERATE: Manual numpy ECDF calculation misses Altair's declarative window transform pattern
    • Fix: Replace numpy sort+arange with transform_window/transform_calculate to compute ranks within Vega-Lite
  2. DE-01 MILD: No value labels on quartile focal points — add a text mark layer with formatted latency values near each marker to make key percentiles immediately readable without hover

AI Feedback for Next Attempt

Strong implementation with correct ECDF step-after interpolation, excellent theming, and good design intent. To elevate further: (1) add a text mark layer on the three quartile focal points showing the latency values (e.g. '~97ms', '~122ms', '~140ms') so key percentiles are readable without hover; (2) use Altair's window transform for the ECDF calculation rather than numpy preprocessing to demonstrate library-native data transformation capabilities; (3) increase Y-axis gridOpacity slightly from 0.10 to 0.13 for marginally improved percentile reading.

Verdict: APPROVED

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

claude Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white #FAF8F1 background (correct, not pure white). Title "ecdf-basic · python · altair · anyplot.ai" in bold dark ink, clearly readable and spanning ~65% of plot width. X-axis label "API Response Time (ms)" with units and Y-axis label "Cumulative Proportion" with percentage tick format (0%–100%) both in dark ink and well-balanced. Single ECDF step-after line in brand green #009E73 at strokeWidth=3.5, vivid and clearly visible. Dashed reference lines (5-4 pattern) in muted gray extend from both axes at Q1/25% (~96ms), median/50% (~122ms), and Q3/75% (~140ms), forming crosshairs. Filled green dot markers at the three quartile intersections. Text annotations "~96ms", "~122ms", "~140ms" offset from the markers. All text is readable against the light background.

Dark render (plot-dark.png): Warm near-black #1A1A17 background (correct, not pure black). Title and all axis labels render in light warm-white text — fully readable, no dark-on-dark issues detected. The ECDF line, focal markers, and dashed reference lines are in identical colors to the light render (#009E73 green for data, muted gray for references). The Imprint palette data color stays constant across themes as required. All tick labels and annotation text are clearly legible against the dark background. Both renders pass the theme-readability checklist.

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

Score: 90/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title=16, axis=12, labels=10). Readable in both themes. Minor: annotation text at fontSize=9 renders at ~36 source-px in 3200×1800; at 400 px mobile scale this is ~4.5 px effective height.
  • VQ-02: No Overlap (6/6) — No collisions. Annotations offset cleanly via dx=8, dy=-5.
  • VQ-03: Element Visibility (6/6) — ECDF line strokeWidth=3.5 and focal markers size=120 are clearly prominent. 250-point data density well-matched to element sizing.
  • VQ-04: Color Accessibility (2/2) — Single CVD-safe brand green series with high contrast on both backgrounds.
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed (3200×1800). Balanced margins, no overflow, no clipping.
  • VQ-06: Axis Labels & Title (2/2) — "API Response Time (ms)" and "Cumulative Proportion" with percentage format. All descriptive with units.
  • VQ-07: Palette Compliance (2/2) — First series #009E73, background #FAF8F1/#1A1A17, all chrome tokens theme-adaptive, data colors identical across both renders.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above a configured default (4): deliberate focal design with intentional color hierarchy (vivid green primary line vs. muted gray secondary references). Not yet at publication-polish level (6+).
  • DE-02: Visual Refinement (4/6) — X-axis grid removed; Y-axis grid at subtle gridOpacity=0.13. Reference lines dashed at opacity=0.75. Clean view configuration. Above the default of 2.
  • DE-03: Data Storytelling (4/6) — Crosshair reference lines + focal dot markers + text labels at three quartiles clearly guide readers to Q1/median/Q3 values. Practical API latency context adds narrative clarity. Above the default of 2.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct ECDF using mark_line(interpolate='step-after') with cume_dist() window transform.
  • SC-02: Required Features (4/4) — Step function, Y-axis 0–1, grid lines, distinct line style all present.
  • SC-03: Data Mapping (3/3) — X: latency_ms (continuous), Y: cumulative proportion 0–1. Full data range (20–260ms) visible.
  • SC-04: Title & Legend (3/3) — Title "ecdf-basic · python · altair · anyplot.ai" matches mandated format exactly. Single series — no legend required.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Full ECDF shape shown with distribution spread, step character, and quartile reading demonstrated.
  • DQ-02: Realistic Context (5/5) — API response latency from production web service — neutral, practical, real-world domain.
  • DQ-03: Appropriate Scale (4/4) — Normal(120ms, 35ms) clipped at 20ms is factually realistic for web API latency distributions.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean linear flow: imports → tokens → data → layers → compose → save → pad. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (3/3) — All imports (os, sys, altair, numpy, pandas, PIL) are used.
  • CQ-04: Code Elegance (2/2) — Elegant declarative approach: transform_window(ecdf='cume_dist()') avoids numpy pre-computation entirely.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html. Canvas padded to exactly 3200×1800 with PIL. Current Altair 6.x API.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) — Expert use of transform_window with cume_dist(), mark_line(interpolate='step-after'), alt.layer() composition, and configure_view/configure_axis/configure_title chaining.
  • LM-02: Distinctive Features (3/5) — transform_window(cume_dist()) for declarative in-Vega ECDF computation is distinctly Vega-Lite/Altair. .interactive() with tooltip encoding adds genuine HTML interactivity. Room to push further (e.g., selection parameters for dynamic percentile highlighting).

Score Caps Applied

  • None

Strengths

  • Correct ECDF step function using Vega-Lite declarative cume_dist() window transform — the idiomatic Altair approach, no numpy pre-computation needed
  • Quartile focal design: crosshair dashed reference lines + filled dot markers + text annotations provide at-a-glance percentile reading in a clean, purposeful hierarchy
  • Full theme adaptation with correct #FAF8F1 / #1A1A17 backgrounds and all chrome elements using theme-adaptive tokens
  • Excellent code quality — KISS structure, deterministic seed, clean imports, canvas padding handled correctly with PIL

Weaknesses

  • Annotation text at fontSize=9 renders at ~36 source-px in the 3200×1800 canvas; at 400 px mobile scale this drops to ~4.5 px effective height — bump to fontSize=11 for better mobile readability
  • Reference lines use opacity=0.75 which can compete visually with the main ECDF line; reducing to opacity=0.5 would strengthen the primary/secondary hierarchy

Issues Found

  1. VQ-01 MINOR: Annotation text at fontSize=9 slightly small for mobile readability
    • Fix: Increase annotation fontSize from 9 to 11 in focal_labels mark_text

AI Feedback for Next Attempt

This is a strong implementation — spec-correct, theme-compliant, and well-designed. Minor improvements: (1) increase annotation fontSize from 9 to 11 for better mobile readability, (2) reduce reference line opacity from 0.75 to 0.5 to improve the visual hierarchy between the primary ECDF line and secondary quartile references.

Verdict: APPROVED

@github-actions github-actions Bot added quality:90 Quality score 90/100 ai-approved Quality OK, ready for merge and removed quality:89 Quality score 89/100 labels Jun 25, 2026
@MarkusNeusinger MarkusNeusinger merged commit ac35e4c into main Jun 25, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/ecdf-basic/altair branch June 25, 2026 09:56
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:90 Quality score 90/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant