diff --git a/plots/scatter-basic/implementations/python/letsplot.py b/plots/scatter-basic/implementations/python/letsplot.py index a058e3f97f..cadf92374c 100644 --- a/plots/scatter-basic/implementations/python/letsplot.py +++ b/plots/scatter-basic/implementations/python/letsplot.py @@ -1,7 +1,7 @@ """ anyplot.ai scatter-basic: Basic Scatter Plot Library: letsplot 4.9.0 | Python 3.14.4 -Quality: 88/100 | Created: 2026-04-23 +Quality: 89/100 | Updated: 2026-04-23 """ import os @@ -32,7 +32,8 @@ PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" -GRID = "#1A1A17" if THEME == "light" else "#F0EFE8" +# Pre-blended ~10% INK over PAGE_BG (element_line has no alpha) +GRID = "#E4E2DB" if THEME == "light" else "#2F2F2C" BRAND = "#009E73" # Okabe-Ito position 1 # Data — study hours vs exam scores (moderate positive correlation) @@ -42,17 +43,17 @@ exam_scores = np.clip(exam_scores, 30, 105) df = pd.DataFrame({"study_hours": study_hours, "exam_scores": exam_scores}) -# Plot +# Plot — shape=21 allows theme-adaptive stroke matching PAGE_BG for marker definition plot = ( ggplot(df, aes(x="study_hours", y="exam_scores")) - + geom_point(color=BRAND, size=6, alpha=0.7, stroke=0.6) + + geom_point(shape=21, fill=BRAND, color=PAGE_BG, size=6, alpha=0.75, stroke=0.8) + labs(x="Study Hours per Day", y="Exam Score (points)", title="scatter-basic · letsplot · anyplot.ai") + ggsize(1600, 900) + theme_minimal() + theme( plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG), - panel_grid_major=element_line(color=GRID, size=0.3), + panel_grid_major=element_line(color=GRID, size=0.4), panel_grid_minor=element_blank(), axis_title=element_text(size=20, color=INK), axis_text=element_text(size=16, color=INK_SOFT), diff --git a/plots/scatter-basic/metadata/python/letsplot.yaml b/plots/scatter-basic/metadata/python/letsplot.yaml index 0f840b40ed..7ebd6bcecf 100644 --- a/plots/scatter-basic/metadata/python/letsplot.yaml +++ b/plots/scatter-basic/metadata/python/letsplot.yaml @@ -2,9 +2,9 @@ library: letsplot language: python specification_id: scatter-basic created: '2025-12-10T20:55:10Z' -updated: '2026-04-23T19:25:04Z' +updated: '2026-04-23T22:09:54Z' generated_by: claude-opus -workflow_run: 24853816154 +workflow_run: 24861090813 issue: 611 python_version: 3.14.4 library_version: 4.9.0 @@ -12,37 +12,42 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-b preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-dark.html -quality_score: 88 +quality_score: 89 review: strengths: - - 'Perfect spec compliance: all required features present, correct title format, - appropriate single-series handling with no legend' - - 'Excellent theme implementation: both renders adapt correctly with proper background/text/chrome - token mapping' - - Clean, readable code with explicit font sizing (24pt title, 20pt labels, 16pt - ticks) and reproducible data generation via np.random.seed(42) - - Generates interactive HTML output alongside PNG — leverages a key lets-plot advantage + - 'Theme-adaptive chrome is fully correct: PAGE_BG, INK, INK_SOFT tokens applied + to all non-data elements in both light and dark renders' + - Shape=21 with PAGE_BG stroke creates subtle marker definition that adapts to theme + — sophisticated approach + - Pre-blended GRID color avoids alpha transparency issues in lets-plot element_line + - All font sizes explicitly set (title=24, axis=20, ticks=16) meeting DPI-based + requirements + - Seed set, axis labels descriptive with units, clean KISS structure, HTML + PNG + export + - Data scenario (study hours vs exam scores) is realistic, neutral, and correctly + shows moderate positive correlation weaknesses: - - 'Grid uses full-opacity INK colors (#1A1A17 light / #F0EFE8 dark) instead of the - recommended ~10% opacity rgba; this makes the dark render grid more visible than - ideal' - - No visual hierarchy or emphasis — the scatter cloud is presented uniformly with - no focal point, trend line, or emphasis on notable data points - - Design aesthetics stay at polished-default level; lacks distinctive styling touches - (e.g., theme-adaptive marker stroke color, trend line) that would elevate it above - a standard library output + - 'DE-03 LOW: Data is displayed but no visual hierarchy or emphasis — viewer must + find their own story. Adding geom_smooth() with a subtle trend line would create + a focal point and guide the viewer to the correlation insight' + - 'DE-01 MODERATE: Design is above defaults but not ''strong design''. Adding a + geom_smooth trend line (with matching INK_SOFT color and high transparency) and + perhaps a subtitle noting the correlation would push this to strong design territory' + - 'LM-02 LOW: Generic ggplot2 grammar with no lets-plot-distinctive features. geom_smooth() + is a natural lets-plot feature that would add storytelling value; theme-native + faceting or using lets_plot tooltips (HTML) are other options' image_description: |- Light render (plot-light.png): Background: Warm off-white #FAF8F1 — correct, not pure white - Chrome: Title "scatter-basic · letsplot · anyplot.ai" bold at 24pt — dark #1A1A17, clearly readable. Axis labels "Study Hours per Day" and "Exam Score (points)" at 20pt — dark, readable. Tick labels at 16pt — muted #4A4A44, readable. Major grid lines visible but thin (size=0.3). No tick marks (removed). Left/bottom axis lines only. - Data: 180 scatter points in brand green #009E73, alpha=0.7, size=6. Clear positive correlation visible. - Legibility verdict: PASS — all text readable against light background, no light-on-light failures + Chrome: Title "scatter-basic · letsplot · anyplot.ai" in bold dark text top-left; axis labels "Study Hours per Day" (x) and "Exam Score (points)" (y) in dark INK color; tick labels in slightly softer INK_SOFT; subtle grid lines; no tick marks + Data: 180 points in brand green #009E73 with shape=21, subtle background-colored stroke for definition, alpha=0.75 — clear positive correlation visible across full range 1–10 hours / 30–105 points + Legibility verdict: PASS — all text clearly readable against warm off-white background Dark render (plot-dark.png): Background: Warm near-black #1A1A17 — correct, not pure black - Chrome: Title in near-white #F0EFE8 — clearly readable against dark background. Axis labels same near-white — readable. Tick labels in muted #B8B7B0 — readable. Grid lines appear as thin light lines on dark surface — slightly more visible than in light render but not dominant (full-opacity #F0EFE8 with size=0.3). - Data: 180 scatter points in identical brand green #009E73 — unchanged from light render, visible and distinguishable against dark background. - Legibility verdict: PASS — all text readable against dark background, no dark-on-dark failures detected + Chrome: Same title, axis labels, and tick labels rendered in light colors (INK=#F0EFE8 and INK_SOFT=#B8B7B0) — clearly readable against dark background; grid lines are very subtle but visible; no dark-on-dark issues detected + Data: Same 180 #009E73 green points — identical color to light render, only chrome flipped — correct Okabe-Ito palette consistency + Legibility verdict: PASS — all text readable; no dark-on-dark failures; brand green #009E73 clearly visible on near-black surface criteria_checklist: visual_quality: score: 30 @@ -53,71 +58,72 @@ review: score: 8 max: 8 passed: true - comment: Title 24pt bold, axis labels 20pt, ticks 16pt — all explicitly set - and readable in both themes + comment: 'All font sizes explicitly set: title=24, axis=20, ticks=16 — perfect + DPI-based sizing' - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No text or label collisions + comment: No text or element overlap in either render - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: size=6, alpha=0.7 well-adapted for 180 points; markers clearly visible + comment: 180 points, size=6, alpha=0.75, shape=21 with stroke — well-adapted + to density - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: 'Okabe-Ito #009E73 provides good contrast on both surfaces; CVD-safe' + comment: 'Single series in Okabe-Ito #009E73 — CVD-safe' - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: 4800x2700 landscape, good margins, plot fills canvas well + comment: Plot fills canvas well with balanced margins - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Study Hours per Day and Exam Score (points) — descriptive with units + comment: 'Both axes descriptive with units: ''Study Hours per Day'', ''Exam + Score (points)''' - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'First series is #009E73; backgrounds correct (#FAF8F1 / #1A1A17); - chrome adapts correctly in both renders' + comment: 'Single series uses brand #009E73; backgrounds #FAF8F1 (light) and + #1A1A17 (dark); theme-correct chrome in both renders' design_excellence: - score: 10 + score: 11 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 4 + score: 5 max: 8 - passed: false - comment: Well-configured and clean but not exceptional; polished library default - rather than distinctive design + passed: true + comment: Above defaults with theme-adaptive stroke, warm backgrounds, and + pre-blended grid — not yet 'strong design' - id: DE-02 name: Visual Refinement score: 4 max: 6 - passed: false - comment: Tick marks removed, minor grid suppressed, axis lines styled. Grid - major lines use full-opacity INK color instead of ~10% rgba — dark render - grid more visible than ideal + passed: true + comment: Minor grid removed, axis ticks removed, subtle grid lines — good + refinement - id: DE-03 name: Data Storytelling score: 2 max: 6 passed: false - comment: Data displayed clearly, positive correlation apparent, but no visual - hierarchy, emphasis, trend line, or focal point + comment: Correlation visible but no visual hierarchy or emphasis — no trend + line, no focal point spec_compliance: score: 15 max: 15 @@ -127,27 +133,26 @@ review: score: 5 max: 5 passed: true - comment: Correct scatter via geom_point() + comment: Correct scatter plot - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Alpha transparency, axis labels, title, grid lines, appropriate point - sizing — all present + comment: Transparency, axis labels, title, grid — all present - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X/Y correctly assigned; all 180 points visible + comment: X=study hours (independent), Y=exam scores (dependent), r~0.7 correlation - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title exactly 'scatter-basic · letsplot · anyplot.ai'; no legend - appropriate for single series + comment: Title 'scatter-basic · letsplot · anyplot.ai' correct; no legend + (single series — appropriate) data_quality: score: 15 max: 15 @@ -157,22 +162,19 @@ review: score: 6 max: 6 passed: true - comment: Clear positive correlation with realistic scatter/noise, outliers - present, full range visible + comment: 'Covers full scatter range: spread, correlation, outliers' - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Study hours vs exam scores — real, relatable, neutral educational - scenario + comment: Study hours vs exam scores — real, neutral, educational scenario - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Hours 1-10/day and scores 30-105 are realistic; moderate r~0.7 correlation - as specified + comment: 1–10 hours/day realistic; scores 30–105 (labeled as points, not %) code_quality: score: 10 max: 10 @@ -182,20 +184,19 @@ review: score: 3 max: 3 passed: true - comment: 'Flat linear code: imports → tokens → data → plot → save; no functions - or classes' + comment: Imports → data → plot → save, no functions/classes - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set + comment: np.random.seed(42) - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used; element_blank used in two theme overrides + comment: All imports used - id: CQ-04 name: Code Elegance score: 2 @@ -207,7 +208,7 @@ review: score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html; current lets-plot API + comment: Saves plot-{THEME}.png and plot-{THEME}.html with scale=3 library_mastery: score: 8 max: 10 @@ -217,16 +218,15 @@ review: score: 5 max: 5 passed: true - comment: 'Expert use of ggplot grammar: aes(), geom_point(), labs(), ggsize(), - theme_minimal() + theme() override, ggsave(scale=3)' + comment: 'Expert ggplot2 grammar: ggplot+geom_point+labs+theme, ggsize, ggsave + with scale' - id: LM-02 name: Distinctive Features score: 3 max: 5 - passed: false - comment: Uses lets-plot-specific ggsize(), scale=3 export for pixel-density, - and HTML export — all distinctive to lets-plot, but no use of advanced lets-plot-only - features like geom_smooth with confidence interval or built-in interactivity + passed: true + comment: shape=21 fill/stroke paradigm and HTML export are lets-plot features, + but no geom_smooth or truly distinctive lets-plot capabilities verdict: REJECTED impl_tags: dependencies: [] @@ -237,3 +237,4 @@ impl_tags: dataprep: [] styling: - alpha-blending + - edge-highlighting