Skip to content

feat(letsplot): implement scatter-connected-temporal#8538

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/scatter-connected-temporal/letsplot
Jun 9, 2026
Merged

feat(letsplot): implement scatter-connected-temporal#8538
MarkusNeusinger merged 6 commits into
mainfrom
implementation/scatter-connected-temporal/letsplot

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Implementation: scatter-connected-temporal - python/letsplot

Implements the python/letsplot version of scatter-connected-temporal.

File: plots/scatter-connected-temporal/implementations/python/letsplot.py

Parent Issue: #4675


🤖 impl-generate workflow

github-actions Bot added 2 commits June 9, 2026 23:28
Regen from quality 90. Addressed:
- Canvas: fixed ggsize(1600,900) scale=3 → ggsize(800,450) scale=4 (3200×1800)
- Theme: added ANYPLOT_THEME env var support; full theme-adaptive chrome
- Background: #FAFBFC → PAGE_BG (#FAF8F1 light / #1A1A17 dark)
- Colors: custom blue gradient → Imprint sequential (#009E73 → #4467A3)
- Text: hardcoded colors → INK/INK_SOFT theme tokens
- Font sizes: scaled down to style-guide values (title 16, axis 12, tick 10)
- Title: corrected format with "python" token and "anyplot.ai"
- Save: plot.png → plot-{THEME}.png + plot-{THEME}.html with path="."
- Annotations: geom_text size 13 → 5 (mm scale, visually larger on canvas)
@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Connected scatter plot on a warm off-white #FAF8F1 background showing the Phillips Curve (unemployment vs. inflation, 1990–2023). A continuous path connects all 34 annual data points, color-coded from brand green #009E73 (1990) to Imprint blue #4467A3 (2023) via imprint_seq. A directional arrow at the terminal path segment (near the 2023 point at ~3.1% unemployment, ~7% inflation) indicates recency. Endpoint markers for 1990 and 2023 are enlarged (size=6) with dark ink rings for emphasis; all other markers are smaller filled circles with a background-colored halo. Year annotations (bold monospace) label 6 key economic turning points. Axis labels read "Unemployment Rate (%)" and "Inflation Rate (%)". Title and subtitle are clearly legible in dark ink. A Year legend (colorbar) appears on the right, labeled 1990/2006/2023. The panel has a visible rectangular box frame. All text is readable against the light background.

Dark render (plot-dark.png): Same data on warm near-black #1A1A17 background. The temporal color gradient is identical to the light render (brand green → Imprint blue) — data colors unchanged as expected. Title, subtitle, axis labels, tick labels, and year annotations all render in light cream/off-white ink and are clearly readable. No dark-on-dark text issues detected. Grid lines are subtle and visible. The box panel border is still present, now rendered in a mid-tone on the dark surface. The 2023 endpoint marker appears with a white ring rather than the dark ink ring, which is correct for the dark theme chrome.

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

Score: 86/100

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

Visual Quality (27/30)

  • VQ-01: Text Legibility (7/8) — All text readable in both themes; year annotation labels at geom_text size=5mm are readable but approach the lower bound for mobile readability at 400px width.
  • VQ-02: No Overlap (5/6) — Year labels are nudged clear of data points. Dense path cluster (~4–6% unemployment) makes individual segments hard to distinguish visually, but no text-on-text or text-on-data collisions.
  • VQ-03: Element Visibility (5/6) — Temporal gradient clearly encoded, endpoint markers well-highlighted, direction arrow prominent. Path alpha=0.75 slightly reduces clarity in the dense mid-section.
  • VQ-04: Color Accessibility (2/2) — imprint_seq (green→blue) is CVD-safe.
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed (3200×1800). No overflow. Good proportions.
  • VQ-06: Axis Labels & Title (2/2) — Descriptive labels with units; subtitle adds narrative context.
  • VQ-07: Palette Compliance (2/2) — Correct imprint_seq gradient (SEQ_LOW=#009E73, SEQ_HIGH=#4467A3). Backgrounds #FAF8F1 / #1A1A17 correct. Both renders theme-correct.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Intentional visual hierarchy: dual point sizes (regular vs endpoint), direction arrow, bold monospace year labels. Subtitle adds Phillips Curve framing. Above baseline quality.
  • DE-02: Visual Refinement (3/6) — theme_minimal() is used but panel_background / panel_border leaves a rectangular box frame visible in both renders. Style guide default is L-shaped frame (remove top and right spines). Grid opacity is well-controlled (rgba 12%), minor grid lines suppressed — good. Legend background uses elevated token correctly.
  • DE-03: Data Storytelling (5/6) — Six key economic turning points annotated (recessions: 2001, 2008–09, 2020; recoveries: 1990s boom, mid-2000s, post-COVID). Color gradient + direction arrow together encode the time dimension without a separate time axis. Clear focal point at the 2023 spike.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Connected scatter with temporal path, exactly as specified.
  • SC-02: Required Features (4/4) — Chronological path (geom_path), color gradient (scale_color_gradient), directional arrow (geom_segment + arrow()), visible point markers (geom_point), year annotations (geom_text).
  • SC-03: Data Mapping (3/3) — X=unemployment, Y=inflation, time_idx as color aesthetic correctly mapped.
  • SC-04: Title & Legend (3/3) — Title is exactly scatter-connected-temporal · python · letsplot · anyplot.ai. Year legend with 1990/2006/2023 labels.

Data Quality (14/15)

  • DQ-01: Feature Coverage (5/6) — Shows scatter points, connecting path, color-encoded temporal progression, directional arrow, and key-event annotations. Full feature set for this plot type.
  • DQ-02: Realistic Context (5/5) — Phillips Curve dynamics 1990–2023 with plausible recession/recovery patterns. Neutral economic data.
  • DQ-03: Appropriate Scale (4/4) — Unemployment 3–10%, inflation -1 to 8%, 34 annual points. Realistic magnitudes for US-style macroeconomic data.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script, no functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42).
  • CQ-03: Clean Imports (2/2) — All imports used; os and standard library not tagged.
  • CQ-04: Code Elegance (2/2) — nudge_map dict, key_years set, df_labels filtering — appropriate complexity for the annotation logic.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html. Current API.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Full ggplot grammar: layered geoms, scale functions, theme(). shape=21 (filled circles with separate stroke color) is idiomatic. Uses ggsize + scale=4 correctly for the required canvas size.
  • LM-02: Distinctive Features (3/5) — layer_tooltips() with formatted field lines is a distinctive letsplot feature. HTML export alongside PNG leverages the interactive runtime. arrow() in geom_segment is idiomatic. Could exploit letsplot's built-in theme switching or livemap integration further, but solid use of its tooltip and export capabilities.

Score Caps Applied

  • None — no cap conditions triggered.

Strengths

  • Full spec compliance: all required features (path, gradient, arrow, annotations, endpoint highlights) implemented correctly.
  • Correct imprint_seq colormap (brand green → Imprint blue) with matching theme-adaptive backgrounds in both renders.
  • Excellent data storytelling: six annotated economic turning points with directional arrow make the temporal narrative self-explanatory.
  • Code quality is exemplary — flat, reproducible, clean imports, elegant nudge_map logic.
  • layer_tooltips() with formatted year/unemployment/inflation fields is a genuine letsplot strength well-exploited.

Weaknesses

  • Panel box frame is present (rectangular border around data area) — style guide default is L-shaped frame (remove top and right spines). Add theme(panel_border=element_blank()) or equivalent.
  • Year annotation font size=5mm is near the lower bound for mobile readability; consider nudging to size=6 for the bold monospace labels.
  • Path alpha=0.75 in the dense cluster (4–6% unemployment range) slightly reduces segment clarity; minor but worth noting for future repair.

Issues Found

  1. DE-02 MEDIUM: Rectangular panel box frame visible in both renders — should be L-shaped.
    • Fix: Add panel_border=element_blank() or panel_ontop=False + remove top/right frame elements in theme().
  2. VQ-01 MINOR: Year annotation labels at size=5mm borderline for mobile.
    • Fix: Increase geom_text size from 5 to 6.

AI Feedback for Next Attempt

Good implementation overall — spec fully satisfied. Primary improvement: remove the rectangular panel box frame (add theme(panel_border=element_blank()) so only left/bottom axes show, matching the L-shaped frame default). Secondary: bump geom_text year labels from size=5 to size=6 for better mobile readability. The imprint_seq palette, theme-adaptive chrome, and layer_tooltips usage are all correct and should be preserved.

Verdict: APPROVED

@github-actions github-actions Bot added quality:86 Quality score 86/100 ai-rejected Quality not OK, triggers update labels Jun 9, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

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

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1). Title "scatter-connected-temporal · python · letsplot · anyplot.ai" in dark ink at top-left; subtitle "Phillips Curve: unemployment vs inflation, 1990–2023" in smaller INK_SOFT — both clearly readable. Axis labels "Unemployment Rate (%)" and "Inflation Rate (%)" in dark ink; tick labels (3–10% x, −1–8% y) in INK_SOFT. Year annotations 1990/2000/2007/2009/2020/2023 in bold monospace dark ink. The connected path runs green (#009E73, 1990) → blue (#4467A3, 2023) via the Imprint sequential gradient. Small circular markers along the path; larger endpoint markers (size=6) with INK border highlight 1990 (green) and 2023 (blue). Directional arrow at terminal segment. Gradient legend ("Year", 1990/2006/2023) on elevated #FFFDF6 background on the right. Subtle grid behind data. All text is clearly readable against the warm off-white background — no light-on-light issues.

Dark render (plot-dark.png): Warm near-black background (#1A1A17). All chrome elements (title, subtitle, axis labels, tick labels, year annotations, legend text) flip to light (#F0EFE8 / #B8B7B0) — every element is clearly readable against the dark surface. No dark-on-dark failures observed. Legend box on elevated dark (#242420) background. Data colors (green-to-blue gradient) are identical to the light render — only the chrome has flipped. Arrow and endpoint highlights use the same gradient values.

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

Score: 88/100

Category Score Max
Visual Quality 28 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 88 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All text readable in both renders; year annotations (geom_text size=6mm ≈ 17pt) are slightly large relative to tick labels but not a legibility failure.
  • VQ-02: No Overlap (5/6) — nudge_map prevents point–label collision effectively; minor visual crowding in the dense 4–6% unemployment cluster but no actual text overlap.
  • VQ-03: Element Visibility (6/6) — Path (size=1.5, alpha=0.75), points (size=3.5), endpoint highlights (size=6), and arrow all clearly visible in both renders.
  • VQ-04: Color Accessibility (2/2) — Imprint sequential gradient (green→blue) is CVD-safe; good contrast in both themes.
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed (3200×1800). Good proportions, legend fits within bounds, no clipping or overflow detected.
  • VQ-06: Axis Labels & Title (2/2) — Both axis labels include units (%). Title format correct. Subtitle provides context.
  • VQ-07: Palette Compliance (2/2) — imprint_seq gradient (#009E73→#4467A3) used correctly for continuous temporal data. Backgrounds #FAF8F1/#1A1A17 correct. Data colors identical across both renders; only chrome flips.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above default (4): temporal gradient encoding, endpoint emphasis via larger markers with INK border, directional arrow, monospace bold annotations, full theme adaptation. Headroom remains: standard horizontal gradient colorbar rather than a more integrated legend design.
  • DE-02: Visual Refinement (4/6) — Above default (2): panel_border removed, minor grid hidden, grid opacity kept subtle (rgba 0.12), generous margins. theme_minimal() base with deliberate overrides.
  • DE-03: Data Storytelling (4/6) — Above default (2): Phillips curve narrative clear, arrow shows direction of time, gradient reinforces temporal flow, turning-point annotations provide economic context.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct connected scatter plot with temporal path.
  • SC-02: Required Features (4/4) — Sequential connections, key-year annotations, directional arrow, visible point markers, temporal color gradient — all present per spec.
  • SC-03: Data Mapping (3/3) — X=unemployment, Y=inflation, time_idx drives color gradient and path ordering. 34 data points (1990–2023) within spec's 10–100 range.
  • SC-04: Title & Legend (3/3) — Title "scatter-connected-temporal · python · letsplot · anyplot.ai" is correct format. Year gradient legend with 1990/2006/2023 labels present.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Full feature set: temporal path, color gradient, arrows, endpoint highlights, interactive tooltips, key-year annotations covering economic turning points.
  • DQ-02: Realistic Context (5/5) — Phillips curve is well-established economics. Unemployment 3.5–10% and inflation −0.4–6.5% are realistic ranges. Turning points (2001, 2008, 2020) historically grounded. Neutral, factual context.
  • DQ-03: Appropriate Scale (4/4) — 34 data points within spec's 10–100 range. Value ranges domain-appropriate.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script, no functions or classes, linear flow.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All lets_plot imports are used; os/numpy/pandas as expected.
  • CQ-04: Code Elegance (2/2) — Appropriate complexity. layer_tooltips() is a real interactive feature, not fake UI.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html. Current API.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Idiomatic ggplot grammar: geom layering, aes() mappings, scale_*_gradient, theme_minimal() + theme() overrides, ggsize(), ggsave(scale=4).
  • LM-02: Distinctive Features (3/5) — Uses layer_tooltips() with custom line formatting (a distinctive letsplot feature), arrow() function, geom_path() for connected ordering, shape=21 fill/stroke split for markers. Above default (1).

Score Caps Applied

  • None

Strengths

  • Full spec compliance — temporal path, directional arrow, Imprint sequential gradient, endpoint highlighting, and key-year annotations all implemented as required
  • Correct imprint_seq gradient (#009E73→#4467A3) for continuous temporal encoding; no forbidden colormaps used
  • Complete theme adaptation with correct token values (PAGE_BG, INK, INK_SOFT, ELEVATED_BG) applied to all chrome elements — both renders fully legible
  • letsplot-native interactive tooltips via layer_tooltips() with formatted year/unemployment/inflation data
  • Compelling Phillips curve narrative with economic turning-point annotations and directional arrow
  • Clean code: flat structure, seed=42, all imports used, correct canvas 800×450 @ scale=4 → 3200×1800

Weaknesses

  • Year annotation text (geom_text size=6 mm ≈ 17pt at source resolution) is slightly large relative to tick labels (10pt); reducing to size=4–5 mm would improve proportional balance
  • Dense mid-plot cluster (unemployment 4–6%, 1990s–2000s regime) makes the temporal path hard to follow locally — fading or thinning earlier path segments (e.g., alpha ramping with time_idx) would improve readability of the historical path
  • DE-01 headroom: standard horizontal gradient colorbar legend; a custom legend approach (e.g., inline year markers at 1990/2006/2023 along the gradient bar) would lift aesthetic sophistication

Issues Found

  1. VQ-01 MINOR: Year annotation fontsize (geom_text size=6 mm) is slightly disproportionate to tick labels
    • Fix: Reduce geom_text size from 6 to 4–5 mm for better proportional balance
  2. DE-01 MODERATE: Standard gradient colorbar; no custom legend design
    • Fix: Consider inline year annotations on the gradient legend or a more integrated year-marker approach

AI Feedback for Next Attempt

This is a strong implementation meeting all spec requirements. Minor improvements: (1) reduce geom_text size from 6 to 4–5 mm for better proportionality, (2) consider ramping path alpha by time_idx so older segments are lighter and the recent trajectory stands out, (3) explore a custom legend approach beyond the standard colorbar.

Verdict: APPROVED

@github-actions github-actions Bot added quality:88 Quality score: 88/100 ai-approved Quality OK, ready for merge and removed quality:86 Quality score 86/100 labels Jun 9, 2026
@MarkusNeusinger MarkusNeusinger merged commit c4c0baa into main Jun 9, 2026
3 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/scatter-connected-temporal/letsplot branch June 9, 2026 23:42
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:88 Quality score: 88/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant