From 51f357475e9794b18e0d7b21a9f17834261b84ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 Jun 2026 23:21:01 +0000 Subject: [PATCH 1/5] feat(altair): implement scatter-connected-temporal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regen from quality 87. Addressed: - Canvas: fixed 620×320 inner view + scale_factor=4.0 + PAD-only to 3200×1800 - Color: replaced forbidden viridis with Imprint sequential (#009E73→#4467A3) - Theme: added full theme-adaptive chrome (PAGE_BG, ELEVATED_BG, INK, INK_SOFT) - Output: fixed file names to plot-{THEME}.png/html - Path opacity: 0.35→0.60 for legible temporal trajectory - Y-axis: tightened domain from [-1.5,5.8] to [-0.8,6.2], removing wasted space - Annotations: improved nudging for dense lower-left cluster (2015, 2023) Co-Authored-By: Claude Sonnet 4.6 --- .../implementations/python/altair.py | 145 ++++++++++++------ 1 file changed, 100 insertions(+), 45 deletions(-) diff --git a/plots/scatter-connected-temporal/implementations/python/altair.py b/plots/scatter-connected-temporal/implementations/python/altair.py index 73add594a5..64baeb3bc1 100644 --- a/plots/scatter-connected-temporal/implementations/python/altair.py +++ b/plots/scatter-connected-temporal/implementations/python/altair.py @@ -1,15 +1,31 @@ -""" pyplots.ai +"""anyplot.ai scatter-connected-temporal: Connected Scatter Plot with Temporal Path Library: altair 6.0.0 | Python 3.14.3 -Quality: 87/100 | Created: 2026-03-13 """ -import altair as alt +import importlib +import os +import sys + + +# This file is named altair.py — remove the script directory from sys.path so +# importlib.import_module('altair') resolves the installed package, not this file. +_path0 = sys.path.pop(0) +alt = importlib.import_module("altair") +sys.path.insert(0, _path0) import numpy as np import pandas as pd +from PIL import Image -# Data — US-style unemployment vs inflation over 30 years +# --- Theme tokens — Imprint palette --- +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" + +# --- Data — US-style unemployment vs inflation (Phillips curve, 1994–2023) --- np.random.seed(42) years = np.arange(1994, 2024) n = len(years) @@ -25,7 +41,7 @@ unemployment[i] = np.clip(unemployment[i], 3.0, 10.5) inflation[i] = np.clip(inflation[i], -0.5, 6.0) -# Add a recession spike around 2008-2010 +# Recession spike around 2008–2010 unemployment[14:17] += np.array([2.5, 4.0, 3.5]) inflation[14:17] -= np.array([1.0, 1.5, 0.5]) unemployment = np.clip(unemployment, 3.0, 10.5) @@ -35,45 +51,46 @@ {"year": years, "unemployment": np.round(unemployment, 1), "inflation": np.round(inflation, 1), "order": range(n)} ) -# Label key time points with nudged positions to avoid crowding +# Key year annotations with nudged positions to avoid crowding label_years = [1994, 2000, 2008, 2010, 2015, 2023] df_labels = df[df["year"].isin(label_years)].copy() -nudge = {2015: (-0.25, 0.35), 2023: (0.25, -0.35)} +nudge = { + 1994: (0.28, 0.30), + 2000: (0.28, 0.30), + 2008: (0.25, -0.32), + 2010: (-0.22, 0.35), + 2015: (0.30, -0.38), + 2023: (-0.28, -0.38), +} df_labels["label_x"] = df_labels.apply(lambda r: r["unemployment"] + nudge.get(r["year"], (0, 0))[0], axis=1) df_labels["label_y"] = df_labels.apply(lambda r: r["inflation"] + nudge.get(r["year"], (0, 0))[1], axis=1) -# Shared axis encodings +# --- Encodings --- x_scale = alt.Scale(domain=[2.5, 8.5], nice=False) -y_scale = alt.Scale(domain=[-1.5, 5.8], nice=False) -axis_config = { - "labelFontWeight": "normal", - "titleColor": "#333333", - "labelColor": "#555555", - "tickColor": "#cccccc", - "gridDash": [3, 3], - "domain": False, -} +# Tightened lower bound — previous [-1.5, 5.8] wasted space below data +y_scale = alt.Scale(domain=[-0.8, 6.2], nice=False) -x_enc = alt.X("unemployment:Q", title="Unemployment Rate (%)", scale=x_scale, axis=alt.Axis(**axis_config)) -y_enc = alt.Y("inflation:Q", title="Inflation Rate (%)", scale=y_scale, axis=alt.Axis(**axis_config)) +x_enc = alt.X("unemployment:Q", title="Unemployment Rate (%)", scale=x_scale) +y_enc = alt.Y("inflation:Q", title="Inflation Rate (%)", scale=y_scale) -# Shared viridis color scale -viridis_scale = alt.Scale(scheme="viridis", domain=[1994, 2023]) -viridis_legend = alt.Legend( - title="Year", titleFontSize=16, labelFontSize=15, format="d", gradientLength=300, gradientThickness=12 +# Imprint sequential colormap for temporal progression: brand-green (1994) → blue (2023) +imprint_seq_scale = alt.Scale(range=["#009E73", "#4467A3"], domain=[1994, 2023]) +year_legend = alt.Legend( + title="Year", titleFontSize=10, labelFontSize=10, format="d", gradientLength=160, gradientThickness=10 ) -# Connecting path in temporal order — neutral gray to avoid color conflicts -path = alt.Chart(df).mark_line(strokeWidth=2.5, opacity=0.35, color="#666666").encode(x=x_enc, y=y_enc, order="order:Q") +# --- Chart layers --- +# Connecting path in temporal order — increased opacity (0.60) for legible trajectory +path = alt.Chart(df).mark_line(strokeWidth=2.5, opacity=0.60, color=INK_SOFT).encode(x=x_enc, y=y_enc, order="order:Q") -# Points colored by temporal progression — carries the viridis legend +# Points colored by temporal progression using Imprint sequential cmap points = ( alt.Chart(df) - .mark_point(filled=True, size=180, stroke="white", strokeWidth=1.2) + .mark_point(filled=True, size=200, stroke="white", strokeWidth=1.2) .encode( x=x_enc, y=y_enc, - color=alt.Color("year:Q", scale=viridis_scale, legend=viridis_legend), + color=alt.Color("year:Q", scale=imprint_seq_scale, legend=year_legend), tooltip=[ alt.Tooltip("year:Q", title="Year", format="d"), alt.Tooltip("unemployment:Q", title="Unemployment (%)", format=".1f"), @@ -82,37 +99,75 @@ ) ) -# Year annotations for key points with nudged positions +# Year annotations for key time points annotations = ( alt.Chart(df_labels) - .mark_text(fontSize=16, fontWeight="bold", color="#333333", dy=-16) + .mark_text(fontSize=11, fontWeight="bold", color=INK, dy=-15) .encode(x=alt.X("label_x:Q"), y=alt.Y("label_y:Q"), text=alt.Text("year:Q", format="d")) ) -# Compose layers +# --- Compose + configure --- +# Canvas: 620×320 inner view (landscape) → target PNG 3200×1800 after scale_factor=4 chart = ( (path + points + annotations) .properties( - width=1600, - height=900, + width=620, + height=320, + background=PAGE_BG, title=alt.Title( - "scatter-connected-temporal · altair · pyplots.ai", - fontSize=28, - color="#222222", + "scatter-connected-temporal · altair · anyplot.ai", + fontSize=16, + color=INK, subtitle="Unemployment vs. Inflation — tracing the Phillips curve path (1994–2023)", - subtitleFontSize=16, - subtitleColor="#777777", - subtitlePadding=6, + subtitleFontSize=10, + subtitleColor=INK_SOFT, + subtitlePadding=4, ), ) + .configure_view(fill=PAGE_BG, strokeWidth=0, continuousWidth=620, continuousHeight=320) .configure_axis( - labelFontSize=18, titleFontSize=22, titlePadding=12, grid=True, gridOpacity=0.15, gridColor="#cccccc" + labelFontSize=10, + labelColor=INK_SOFT, + titleFontSize=12, + titleColor=INK, + titlePadding=8, + domainColor=INK_SOFT, + tickColor=INK_SOFT, + grid=True, + gridOpacity=0.15, + gridColor=INK, + gridDash=[3, 3], + ) + .configure_title(color=INK) + .configure_legend( + orient="right", + padding=10, + fillColor=ELEVATED_BG, + strokeColor=INK_SOFT, + labelColor=INK_SOFT, + titleColor=INK, + labelFontSize=10, + titleFontSize=10, ) - .configure_view(strokeWidth=0) - .configure_legend(orient="right", padding=10) .interactive() ) -# Save -chart.save("plot.png", scale_factor=3.0) -chart.save("plot.html") +# --- Save --- +TW, TH = 3200, 1800 +chart.save(f"plot-{THEME}.png", scale_factor=4.0) + +# PAD-only to exact 3200×1800 — do NOT crop (cropping clips labels, triggers AR-09) +_img = Image.open(f"plot-{THEME}.png").convert("RGB") +_w, _h = _img.size +if _w > TW or _h > TH: + raise SystemExit( + f"altair vl-convert produced {_w}×{_h}, exceeds target {TW}×{TH}. " + f"Shrink chart .properties(width=, height=) values and re-render." + ) +if _w < TW or _h < TH: + _canvas = Image.new("RGB", (TW, TH), PAGE_BG) + _canvas.paste(_img, ((TW - _w) // 2, (TH - _h) // 2)) + _canvas.save(f"plot-{THEME}.png") + +# Interactive HTML — untouched by padding +chart.save(f"plot-{THEME}.html") From 798844529b1a4fe1dc2c250f2686cbf35b468deb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 Jun 2026 23:21:13 +0000 Subject: [PATCH 2/5] chore(altair): add metadata for scatter-connected-temporal --- .../metadata/python/altair.yaml | 244 ++---------------- 1 file changed, 16 insertions(+), 228 deletions(-) diff --git a/plots/scatter-connected-temporal/metadata/python/altair.yaml b/plots/scatter-connected-temporal/metadata/python/altair.yaml index 43f8639863..f5b66c5f0c 100644 --- a/plots/scatter-connected-temporal/metadata/python/altair.yaml +++ b/plots/scatter-connected-temporal/metadata/python/altair.yaml @@ -1,233 +1,21 @@ +# Per-library metadata for altair implementation of scatter-connected-temporal +# Auto-generated by impl-generate.yml + library: altair +language: python specification_id: scatter-connected-temporal created: '2026-03-13T15:26:15Z' -updated: '2026-03-13T15:56:32Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 23057665486 +updated: '2026-06-09T23:21:12Z' +generated_by: claude-sonnet +workflow_run: 27241876474 issue: 4675 -python_version: 3.14.3 -library_version: 6.0.0 -preview_url: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/altair/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/altair/plot.html -quality_score: 87 +language_version: 3.13.13 +library_version: 6.2.1 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-dark.html +quality_score: null review: - strengths: - - 'Excellent spec compliance with all required features: temporal ordering, annotations, - color gradient, and point markers' - - Strong design with viridis color encoding, white point strokes, subtle gray path, - and removed spines - - Realistic and neutral Phillips curve data with convincing recession dynamics - - Clean well-organized code following KISS principles with proper reproducibility - - 'Good use of Altair-specific features: interactive tooltips, HTML export, declarative - layer composition' - weaknesses: - - Connecting path opacity (0.35) is too subtle making temporal trajectory hard to - follow visually - - Lower-left cluster of recent years is dense making individual year progression - difficult to trace - - Y-axis domain extends well below the data range wasting vertical space - image_description: 'The plot displays a connected scatter plot tracing the path - of unemployment rate (%) vs. inflation rate (%) from 1994 to 2023. Points are - colored using a viridis gradient from dark purple (1994) to yellow (2023), connected - by a subtle gray line (opacity ~0.35) following temporal order. Six key years - are annotated in bold text: 1994, 2000, 2008, 2010, 2015, and 2023. The x-axis - spans approximately 2.6–8.4% unemployment and the y-axis from -1.5% to 5.5% inflation. - A vertical viridis color legend labeled "Year" appears on the right. The title - reads "scatter-connected-temporal · altair · pyplots.ai" with a subtitle "Unemployment - vs. Inflation — tracing the Phillips curve path (1994–2023)". The view has no - spines, a subtle dashed grid, and a clean white background. The 2008–2010 recession - spike creates a dramatic rightward excursion, while later years cluster in the - lower-left with low unemployment and low inflation.' - criteria_checklist: - visual_quality: - score: 26 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 7 - max: 8 - passed: true - comment: All font sizes explicitly set (title 28, axis titles 22, ticks 18, - annotations 16). Legend labels slightly smaller than ideal at 15. - - id: VQ-02 - name: No Overlap - score: 5 - max: 6 - passed: true - comment: Lower-left cluster is dense with labels and points close together. - Nudging helps but area is still somewhat crowded. - - id: VQ-03 - name: Element Visibility - score: 5 - max: 6 - passed: true - comment: Points well-sized (180) for 30 data points with white stroke. Path - line at 0.35 opacity is quite subtle and hard to follow in places. - - id: VQ-04 - name: Color Accessibility - score: 4 - max: 4 - passed: true - comment: Viridis colormap is perceptually uniform and colorblind-safe. - - id: VQ-05 - name: Layout & Canvas - score: 3 - max: 4 - passed: true - comment: 4800x2700 output. Y-axis extends to -1.5 but data only reaches -0.5, - wasting some vertical space. - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: 'Descriptive labels with units: Unemployment Rate (%) and Inflation - Rate (%).' - design_excellence: - score: 15 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 6 - max: 8 - passed: true - comment: Strong design with viridis palette, white stroke on points, gray - connecting path, intentional title hierarchy. Above defaults but not FiveThirtyEight-level. - - id: DE-02 - name: Visual Refinement - score: 5 - max: 6 - passed: true - comment: Spines removed, grid subtle (opacity 0.15, dashed), tick colors customized, - generous whitespace. - - id: DE-03 - name: Data Storytelling - score: 4 - max: 6 - passed: true - comment: Key years annotated for narrative, recession spike is visually dramatic, - subtitle provides analytical context. Dense lower-left weakens the ending. - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct connected scatter plot with temporal path. - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: 'All features present: temporal ordering, annotations, color gradient, - point markers.' - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: X=unemployment, Y=inflation, temporal ordering correct. - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title format correct. Year legend with viridis gradient properly - formatted. - data_quality: - score: 14 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 5 - max: 6 - passed: true - comment: Shows cyclical patterns, regime changes (2008 recession), directional - trends. Dense lower-left makes individual paths harder to trace. - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: US-style unemployment vs inflation (Phillips curve) is well-known - and neutral. - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: Realistic ranges for unemployment (3-10.5%) and inflation (-0.5-6%). - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: Clean Imports-Data-Plot-Save flow, no functions or classes. - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: np.random.seed(42) set. - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: altair, numpy, pandas all used. - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Well-organized with shared axis config and nudge dictionary. - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves plot.png and plot.html with current Altair 6.0 API. - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: Declarative encoding, layer composition with + operator, order encoding - for temporal path, configure_axis/configure_view. - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: Interactive tooltips, .interactive() zoom/pan, HTML export, declarative - grammar of graphics. - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - annotations - - layer-composition - - hover-tooltips - - html-export - patterns: - - data-generation - dataprep: [] - styling: - - custom-colormap - - alpha-blending - - grid-styling - - edge-highlighting + strengths: [] + weaknesses: [] From 144f54f64e941372e7b645c243953dcbec198f3c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 Jun 2026 23:28:38 +0000 Subject: [PATCH 3/5] chore(altair): update quality score 86 and review feedback for scatter-connected-temporal --- .../implementations/python/altair.py | 5 +- .../metadata/python/altair.yaml | 243 +++++++++++++++++- 2 files changed, 239 insertions(+), 9 deletions(-) diff --git a/plots/scatter-connected-temporal/implementations/python/altair.py b/plots/scatter-connected-temporal/implementations/python/altair.py index 64baeb3bc1..a2ff274d24 100644 --- a/plots/scatter-connected-temporal/implementations/python/altair.py +++ b/plots/scatter-connected-temporal/implementations/python/altair.py @@ -1,6 +1,7 @@ -"""anyplot.ai +""" anyplot.ai scatter-connected-temporal: Connected Scatter Plot with Temporal Path -Library: altair 6.0.0 | Python 3.14.3 +Library: altair 6.2.1 | Python 3.13.13 +Quality: 86/100 | Updated: 2026-06-09 """ import importlib diff --git a/plots/scatter-connected-temporal/metadata/python/altair.yaml b/plots/scatter-connected-temporal/metadata/python/altair.yaml index f5b66c5f0c..4b0b8df674 100644 --- a/plots/scatter-connected-temporal/metadata/python/altair.yaml +++ b/plots/scatter-connected-temporal/metadata/python/altair.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for altair implementation of scatter-connected-temporal -# Auto-generated by impl-generate.yml - library: altair language: python specification_id: scatter-connected-temporal created: '2026-03-13T15:26:15Z' -updated: '2026-06-09T23:21:12Z' +updated: '2026-06-09T23:28:38Z' generated_by: claude-sonnet workflow_run: 27241876474 issue: 4675 @@ -15,7 +12,239 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-c preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-dark.html -quality_score: null +quality_score: 86 review: - strengths: [] - weaknesses: [] + strengths: + - Correct use of imprint_seq (#009E73→#4467A3) for temporal encoding — exactly the + right continuous colormap choice for single-polarity data + - Idiomatic Altair layer composition (mark_line + mark_point + mark_text) with proper + order channel for the temporal path + - Theme adaptation fully correct — all chrome elements use INK/INK_SOFT tokens; + both renders are legible without dark-on-dark failures + - Canvas sizing follows library rules (620×320 inner view + PAD-only block) — gate + passed cleanly + weaknesses: + - 'Title missing python language token — fix: change the alt.Title string to "scatter-connected-temporal + · python · altair · anyplot.ai"' + - Dense post-2015 cluster (lower left, unemployment ~3–3.5%, inflation ~0–0.5%) + has multiple overlapping markers and tangled connecting lines — consider reducing + marker size to ~140 or adding slight alpha (opacity=0.75 on points) to improve + separation + - No directional arrow along the temporal path (spec suggested this) — could add + an arrow annotation at a mid-path segment to explicitly indicate the direction + of time flow + image_description: |- + Light render (plot-light.png): + Background: Warm off-white #FAF8F1 — correct, not pure white + Chrome: Title "scatter-connected-temporal · altair · anyplot.ai" bold and fully visible; subtitle legible at 10pt; axis labels "Unemployment Rate (%)" and "Inflation Rate (%)" at 12pt readable; tick labels at 10pt readable; all dark text on light background + Data: 30 filled circle markers colored by Imprint sequential gradient (#009E73 green for 1994 → #4467A3 blue for 2023) with white stroke edges; connecting lines in INK_SOFT gray at opacity 0.60; year annotations (1994, 2000, 2008, 2010, 2015, 2023) in bold dark text; gradient colorbar legend on right + Legibility verdict: PASS — all text readable; dense lower-left cluster has overlapping markers but annotation labels remain legible + + Dark render (plot-dark.png): + Background: Warm near-black #1A1A17 — correct, not pure black + Chrome: Title, subtitle, axis labels, tick labels, legend text all use light text (#F0EFE8 / #B8B7B0); no dark-on-dark failures observed; year annotations render in bright near-white (#F0EFE8) clearly visible; legend box uses #242420 elevated background with appropriate light text + Data: Color gradient identical to light render — brand green (#009E73) for 1994, blue (#4467A3) for 2023; connecting lines in lighter INK_SOFT gray (#B8B7B0) remain clearly visible against dark background; all data colors unchanged between themes + Legibility verdict: PASS — all text readable in dark mode; no dark-on-dark issues; brand green #009E73 clearly visible on dark background + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All text legible in both themes; annotation labels in dense lower-left + cluster read slightly small at thumbnail scale + - id: VQ-02 + name: No Overlap + score: 5 + max: 6 + passed: true + comment: Annotations well-nudged; dense post-2015 cluster has overlapping + markers and tangled lines + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: 30 points at size=200 prominent; white strokes aid separation; connecting + lines at opacity=0.60 visible + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Imprint sequential scale is CVD-safe; no red-green sole differentiator + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas gate passed; no clipping; proportions well-balanced; generous + whitespace + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Descriptive axis labels with units; subtitle adds context + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'imprint_seq range [#009E73, #4467A3] correct; backgrounds #FAF8F1/#1A1A17 + correct; both themes chrome-correct' + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: Intentional Imprint sequential palette, white strokes, subtitle hierarchy, + theme-adaptive chrome; clean-functional rather than editorially crafted + - id: DE-02 + name: Visual Refinement + score: 3 + max: 6 + passed: true + comment: Dashed grid at 15% opacity; view frame removed (strokeWidth=0); above + default but limited explicit refinement + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Year annotations at key inflection points; subtitle names Phillips + curve; no directional arrow; no recession spike emphasis + spec_compliance: + score: 13 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct connected scatter plot with temporal path + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Chronological order via order channel; key year annotations; color + gradient; visible markers + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: Unemployment x-axis, inflation y-axis; time as color and order; all + points in bounds + - id: SC-04 + name: Title & Legend + score: 1 + max: 3 + passed: false + comment: 'Missing python language token — actual: ''scatter-connected-temporal + · altair · anyplot.ai'', required: ''scatter-connected-temporal · python + · altair · anyplot.ai''. Legend colorbar correct.' + data_quality: + score: 14 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 5 + max: 6 + passed: true + comment: Demonstrates connected scatter, temporal path, cyclical patterns, + regime change; synthetic data slightly idealized + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: US unemployment vs inflation 1994-2023 Phillips curve context; plausible + values; neutral economic data + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: x [2.5,8.5] and y [-0.8,6.2] match realistic US ranges; 30 annual + points ideal + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: No functions or classes; linear script + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) before data generation + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All imports used; importlib/sys workaround necessary + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean layer composition; .interactive() is genuine; PAD-only guard + prevents AR-09 + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and .html; uses Altair 6 API correctly + library_mastery: + score: 9 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: Correct layer composition, order channel, alt.Color with custom scale, + configure_* methods + - id: LM-02 + name: Distinctive Features + score: 4 + max: 5 + passed: true + comment: Layer composition, order channel, alt.Title with subtitle, gradient + legend, interactive tooltips; no Altair-specific transforms + verdict: APPROVED +impl_tags: + dependencies: + - pillow + techniques: + - layer-composition + - annotations + - hover-tooltips + - html-export + patterns: + - data-generation + dataprep: [] + styling: + - custom-colormap + - alpha-blending + - edge-highlighting From dd334ca59e5f9ea550da00826739e67dd9a0829e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 Jun 2026 23:30:17 +0000 Subject: [PATCH 4/5] fix(altair): address review feedback for scatter-connected-temporal Attempt 1/3 - fixes based on AI review --- .../implementations/python/altair.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plots/scatter-connected-temporal/implementations/python/altair.py b/plots/scatter-connected-temporal/implementations/python/altair.py index a2ff274d24..2c479e5cea 100644 --- a/plots/scatter-connected-temporal/implementations/python/altair.py +++ b/plots/scatter-connected-temporal/implementations/python/altair.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai scatter-connected-temporal: Connected Scatter Plot with Temporal Path Library: altair 6.2.1 | Python 3.13.13 Quality: 86/100 | Updated: 2026-06-09 @@ -87,7 +87,7 @@ # Points colored by temporal progression using Imprint sequential cmap points = ( alt.Chart(df) - .mark_point(filled=True, size=200, stroke="white", strokeWidth=1.2) + .mark_point(filled=True, size=160, opacity=0.85, stroke="white", strokeWidth=1.2) .encode( x=x_enc, y=y_enc, @@ -116,7 +116,7 @@ height=320, background=PAGE_BG, title=alt.Title( - "scatter-connected-temporal · altair · anyplot.ai", + "scatter-connected-temporal · python · altair · anyplot.ai", fontSize=16, color=INK, subtitle="Unemployment vs. Inflation — tracing the Phillips curve path (1994–2023)", From 8d9cdf94432be2c6fe6cd45811e10d700b05d6e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 9 Jun 2026 23:37:11 +0000 Subject: [PATCH 5/5] chore(altair): update quality score 89 and review feedback for scatter-connected-temporal --- .../implementations/python/altair.py | 4 +- .../metadata/python/altair.yaml | 183 ++++++++++-------- 2 files changed, 107 insertions(+), 80 deletions(-) diff --git a/plots/scatter-connected-temporal/implementations/python/altair.py b/plots/scatter-connected-temporal/implementations/python/altair.py index 2c479e5cea..0abb1dd132 100644 --- a/plots/scatter-connected-temporal/implementations/python/altair.py +++ b/plots/scatter-connected-temporal/implementations/python/altair.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai scatter-connected-temporal: Connected Scatter Plot with Temporal Path Library: altair 6.2.1 | Python 3.13.13 -Quality: 86/100 | Updated: 2026-06-09 +Quality: 89/100 | Updated: 2026-06-09 """ import importlib diff --git a/plots/scatter-connected-temporal/metadata/python/altair.yaml b/plots/scatter-connected-temporal/metadata/python/altair.yaml index 4b0b8df674..80bf605ed1 100644 --- a/plots/scatter-connected-temporal/metadata/python/altair.yaml +++ b/plots/scatter-connected-temporal/metadata/python/altair.yaml @@ -2,7 +2,7 @@ library: altair language: python specification_id: scatter-connected-temporal created: '2026-03-13T15:26:15Z' -updated: '2026-06-09T23:28:38Z' +updated: '2026-06-09T23:37:11Z' generated_by: claude-sonnet workflow_run: 27241876474 issue: 4675 @@ -12,39 +12,46 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-c preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-connected-temporal/python/altair/plot-dark.html -quality_score: 86 +quality_score: 89 review: strengths: - - Correct use of imprint_seq (#009E73→#4467A3) for temporal encoding — exactly the - right continuous colormap choice for single-polarity data - - Idiomatic Altair layer composition (mark_line + mark_point + mark_text) with proper - order channel for the temporal path - - Theme adaptation fully correct — all chrome elements use INK/INK_SOFT tokens; - both renders are legible without dark-on-dark failures - - Canvas sizing follows library rules (620×320 inner view + PAD-only block) — gate - passed cleanly + - 'Temporal color gradient uses correct imprint_seq range (#009E73 → #4467A3), encoding + time direction visually in the most appropriate Altair-idiomatic way' + - Layer composition (path + points + annotations) is textbook Altair — order:Q encoding + for the connecting line is a library-specific feature that non-Altair users would + not discover easily + - 'Theme-adaptive chrome is thorough: PAGE_BG, ELEVATED_BG, INK, INK_SOFT all thread + through configure_axis, configure_legend, configure_title, and mark_text color + — both renders pass the legibility check' + - Year annotations with explicit nudge offsets avoid naive label-point collisions; + the 2008 recession spike and the 2023 low-inflation cluster are correctly identified + and labelled + - Canvas handling follows the PAD-only pattern exactly — raises SystemExit if vl-convert + overshoots, pads with PAGE_BG if undershoots — no crop risk weaknesses: - - 'Title missing python language token — fix: change the alt.Title string to "scatter-connected-temporal - · python · altair · anyplot.ai"' - - Dense post-2015 cluster (lower left, unemployment ~3–3.5%, inflation ~0–0.5%) - has multiple overlapping markers and tangled connecting lines — consider reducing - marker size to ~140 or adding slight alpha (opacity=0.75 on points) to improve - separation - - No directional arrow along the temporal path (spec suggested this) — could add - an arrow annotation at a mid-path segment to explicitly indicate the direction - of time flow + - 'Mild annotation crowding: ''1994'' (nudged to y≈3.3) and ''2010'' (nudged to + y≈2.95) are vertically close in the right-centre cluster; consider increasing + the y-nudge for 1994 from 0.30 to 0.55 so the two bold labels have a full text-line + of separation' + - 'DQ-03: Data is plausibly realistic but synthetically generated; the 2008 unemployment + spike is hand-tuned rather than sourced from actual Bureau of Labor Statistics + figures — values are reasonable but not fact-checked against historical records' + - DE-01 is above generic defaults (temporal gradient is intentional) but the connecting + path uses a plain gray (INK_SOFT) with no arrowheads or directional marker — an + arrow at the final point or a slightly tapered path would lift the storytelling + from good to excellent image_description: |- Light render (plot-light.png): - Background: Warm off-white #FAF8F1 — correct, not pure white - Chrome: Title "scatter-connected-temporal · altair · anyplot.ai" bold and fully visible; subtitle legible at 10pt; axis labels "Unemployment Rate (%)" and "Inflation Rate (%)" at 12pt readable; tick labels at 10pt readable; all dark text on light background - Data: 30 filled circle markers colored by Imprint sequential gradient (#009E73 green for 1994 → #4467A3 blue for 2023) with white stroke edges; connecting lines in INK_SOFT gray at opacity 0.60; year annotations (1994, 2000, 2008, 2010, 2015, 2023) in bold dark text; gradient colorbar legend on right - Legibility verdict: PASS — all text readable; dense lower-left cluster has overlapping markers but annotation labels remain legible + Background: Warm off-white (#FAF8F1) — correct, not pure white + Chrome: Title "scatter-connected-temporal · python · altair · anyplot.ai" in dark ink (~16px, readable); subtitle "Unemployment vs. Inflation — tracing the Phillips curve path (1994–2023)" in INK_SOFT; x-axis label "Unemployment Rate (%)" and y-axis label "Inflation Rate (%)" both readable with units; tick labels legible; Year gradient legend on the right with labels "1994" and "2023" + Data: Scatter markers sized ~160 (Altair area units) with white stroke, colored on a green (#009E73) to blue (#4467A3) gradient encoding temporal progression 1994→2023; connecting path in gray (INK_SOFT, opacity=0.60) traces chronological order; bold year annotations at 1994, 2000, 2008, 2010, 2015, 2023 with nudged positions; 2008 recession spike visible as rightward excursion to ~7.9% unemployment; 2015–2023 cluster compressed in lower-left + Legibility verdict: PASS — all text readable against the warm off-white background; minor annotation crowding between "1994" and "2010" labels (close vertically in right cluster) but no pixel-level overlap Dark render (plot-dark.png): - Background: Warm near-black #1A1A17 — correct, not pure black - Chrome: Title, subtitle, axis labels, tick labels, legend text all use light text (#F0EFE8 / #B8B7B0); no dark-on-dark failures observed; year annotations render in bright near-white (#F0EFE8) clearly visible; legend box uses #242420 elevated background with appropriate light text - Data: Color gradient identical to light render — brand green (#009E73) for 1994, blue (#4467A3) for 2023; connecting lines in lighter INK_SOFT gray (#B8B7B0) remain clearly visible against dark background; all data colors unchanged between themes - Legibility verdict: PASS — all text readable in dark mode; no dark-on-dark issues; brand green #009E73 clearly visible on dark background + Background: Warm near-black (#1A1A17) — correct, not pure black + Chrome: Title and all text rendered in light ink (INK=#F0EFE8 / INK_SOFT=#B8B7B0); axis labels, tick labels, legend title "Year", and legend tick labels "1994"/"2023" all clearly visible against the dark surface; year annotations in INK (light) — no dark-on-dark failures detected + Data: Scatter marker colors identical to light render — green (#009E73) at 1994 end of gradient through blue (#4467A3) at 2023 end; connecting path visible in INK_SOFT (muted light gray); grid lines subtle dashed in light tone at 0.15 opacity; legend gradient bar and elevated background (#242420) correctly themed + Legibility verdict: PASS — all chrome correctly flipped; data colors are identical to light render as required; no dark-on-dark failures criteria_checklist: visual_quality: score: 28 @@ -55,50 +62,58 @@ review: score: 7 max: 8 passed: true - comment: All text legible in both themes; annotation labels in dense lower-left - cluster read slightly small at thumbnail scale + comment: All font sizes explicitly set (title=16, subtitle=10, axis labels=12, + ticks=10, annotations=11); proportions well-balanced; minor crowding of + '1994' and '2010' labels in the right cluster (vertically close, ~0.35 unit + gap) - id: VQ-02 name: No Overlap score: 5 max: 6 passed: true - comment: Annotations well-nudged; dense post-2015 cluster has overlapping - markers and tangled lines + comment: Nudge offsets prevent most label-point collisions; '1994' and '2010' + annotations are close vertically but do not pixel-overlap; mild crowding + in left 2015-2023 cluster is tolerable - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: 30 points at size=200 prominent; white strokes aid separation; connecting - lines at opacity=0.60 visible + comment: 30 data points with size=160 and opacity=0.85 is well-calibrated + for the density; white stroke (strokeWidth=1.2) adds clear definition; connecting + path at opacity=0.60 is appropriately subdued - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Imprint sequential scale is CVD-safe; no red-green sole differentiator + comment: Green-to-blue gradient is CVD-safe (differs in both hue and lightness + under deuteranopia/protanopia); white marker strokes provide luminance separation + from background - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: Canvas gate passed; no clipping; proportions well-balanced; generous - whitespace + comment: Canvas gate passed (no /tmp/anyplot-canvas-gate.txt); plot fills + canvas well with balanced margins; legend well-positioned on right side; + no overflow or clipping - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Descriptive axis labels with units; subtitle adds context + comment: '''Unemployment Rate (%)'' and ''Inflation Rate (%)'' — both descriptive + with units' - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'imprint_seq range [#009E73, #4467A3] correct; backgrounds #FAF8F1/#1A1A17 - correct; both themes chrome-correct' + comment: 'imprint_seq gradient #009E73→#4467A3 for continuous temporal data; + backgrounds #FAF8F1/#1A1A17 correct; all chrome theme-adaptive in both renders' design_excellence: - score: 12 + score: 13 max: 20 items: - id: DE-01 @@ -106,24 +121,28 @@ review: score: 5 max: 8 passed: true - comment: Intentional Imprint sequential palette, white strokes, subtitle hierarchy, - theme-adaptive chrome; clean-functional rather than editorially crafted + comment: 'Above a configured default: temporal gradient encoding, white-stroked + markers, INK_SOFT path color intentionally subdued to let data colors dominate, + subtitle with softer color; not yet publication-ready because path has no + directional cue (arrow/taper)' - id: DE-02 name: Visual Refinement - score: 3 + score: 4 max: 6 passed: true - comment: Dashed grid at 15% opacity; view frame removed (strokeWidth=0); above - default but limited explicit refinement + comment: Dashed grid (gridDash=[3,3]) at 0.15 opacity is subtle; view box + removed (strokeWidth=0); legend styled with ELEVATED_BG fill and INK_SOFT + stroke; axis domain lines visible but not heavy - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Year annotations at key inflection points; subtitle names Phillips - curve; no directional arrow; no recession spike emphasis + comment: Temporal color gradient + year annotations + subtitle 'Phillips curve + path' create a coherent narrative; 2008 recession spike visible as rightward + excursion; visual hierarchy works — viewer can follow the path chronologically spec_compliance: - score: 13 + score: 15 max: 15 items: - id: SC-01 @@ -131,54 +150,57 @@ review: score: 5 max: 5 passed: true - comment: Correct connected scatter plot with temporal path + comment: 'Correct connected scatter plot: mark_point for data markers + mark_line + with order:Q encoding for temporal path' - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Chronological order via order channel; key year annotations; color - gradient; visible markers + comment: 'All spec features: chronological connection, year annotations at + key points (1994, 2000, 2008, 2010, 2015, 2023), temporal color gradient, + visible point markers' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Unemployment x-axis, inflation y-axis; time as color and order; all - points in bounds + comment: X=Unemployment Rate, Y=Inflation Rate; all 30 years (1994-2023) visible + within domain - id: SC-04 name: Title & Legend - score: 1 + score: 3 max: 3 - passed: false - comment: 'Missing python language token — actual: ''scatter-connected-temporal - · altair · anyplot.ai'', required: ''scatter-connected-temporal · python - · altair · anyplot.ai''. Legend colorbar correct.' + passed: true + comment: Title exactly 'scatter-connected-temporal · python · altair · anyplot.ai'; + Year legend correctly labeled with gradient scale data_quality: score: 14 max: 15 items: - id: DQ-01 name: Feature Coverage - score: 5 + score: 6 max: 6 passed: true - comment: Demonstrates connected scatter, temporal path, cyclical patterns, - regime change; synthetic data slightly idealized + comment: 'Shows all plot-type features: temporal path through 2D space, direction + via color gradient, key period annotations, recession spike as dramatic + deviation from steady trend' - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: US unemployment vs inflation 1994-2023 Phillips curve context; plausible - values; neutral economic data + comment: US unemployment vs. inflation (Phillips curve) is a canonical real-world + economic scenario; neutral, non-controversial, comprehensible - id: DQ-03 name: Appropriate Scale - score: 4 + score: 3 max: 4 passed: true - comment: x [2.5,8.5] and y [-0.8,6.2] match realistic US ranges; 30 annual - points ideal + comment: Unemployment 3-10.5% and inflation -0.5 to 6% are realistic US ranges; + 2008 spike deliberately added; values plausible but data is synthetic, not + actual BLS/CPI figures code_quality: score: 10 max: 10 @@ -188,32 +210,35 @@ review: score: 3 max: 3 passed: true - comment: No functions or classes; linear script + comment: 'Flat structure: imports → data → encodings → layers → compose → + save; importlib workaround is necessary (file named altair.py)' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) before data generation + comment: np.random.seed(42) set - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used; importlib/sys workaround necessary + comment: altair (via importlib), numpy, pandas, PIL — all used; sys/os/importlib + required for the filename workaround - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clean layer composition; .interactive() is genuine; PAD-only guard - prevents AR-09 + comment: Nudge dict, layer composition, configure chain — clean and appropriate; + PAD-only canvas handling correctly implemented - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and .html; uses Altair 6 API correctly + comment: Saves plot-{THEME}.png and plot-{THEME}.html; current Altair 6.x + API library_mastery: score: 9 max: 10 @@ -223,28 +248,30 @@ review: score: 5 max: 5 passed: true - comment: Correct layer composition, order channel, alt.Color with custom scale, - configure_* methods + comment: 'Expert Altair: order:Q encoding for temporal line ordering, + operator + for layer composition, configure_* chain for global theming, alt.Title with + subtitle, alt.Scale/Legend with explicit params' - id: LM-02 name: Distinctive Features score: 4 max: 5 passed: true - comment: Layer composition, order channel, alt.Title with subtitle, gradient - legend, interactive tooltips; no Altair-specific transforms + comment: order:Q encoding is a distinctive Altair pattern not available in + matplotlib/seaborn; layer composition and interactive tooltips are Altair-native; + alt.Title subtitle separation is a VL-specific feature verdict: APPROVED impl_tags: dependencies: - pillow techniques: - - layer-composition - annotations - hover-tooltips - html-export + - layer-composition patterns: - data-generation dataprep: [] styling: - - custom-colormap - alpha-blending + - custom-colormap - edge-highlighting