Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions plots/scatter-basic/implementations/python/letsplot.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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),
Expand Down
135 changes: 68 additions & 67 deletions plots/scatter-basic/metadata/python/letsplot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,52 @@ 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
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-light.png
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 #009E73unchanged 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 pointsidentical 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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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: []
Expand All @@ -237,3 +237,4 @@ impl_tags:
dataprep: []
styling:
- alpha-blending
- edge-highlighting
Loading