Skip to content

Commit d912448

Browse files
feat(letsplot): implement scatter-basic (#5326)
## Implementation: `scatter-basic` - python/letsplot Implements the **python/letsplot** version of `scatter-basic`. **File:** `plots/scatter-basic/implementations/python/letsplot.py` **Parent Issue:** #611 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24861090813)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent ec35031 commit d912448

2 files changed

Lines changed: 74 additions & 72 deletions

File tree

plots/scatter-basic/implementations/python/letsplot.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" anyplot.ai
22
scatter-basic: Basic Scatter Plot
33
Library: letsplot 4.9.0 | Python 3.14.4
4-
Quality: 88/100 | Created: 2026-04-23
4+
Quality: 89/100 | Updated: 2026-04-23
55
"""
66

77
import os
@@ -32,7 +32,8 @@
3232
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
3333
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
3434
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
35-
GRID = "#1A1A17" if THEME == "light" else "#F0EFE8"
35+
# Pre-blended ~10% INK over PAGE_BG (element_line has no alpha)
36+
GRID = "#E4E2DB" if THEME == "light" else "#2F2F2C"
3637
BRAND = "#009E73" # Okabe-Ito position 1
3738

3839
# Data — study hours vs exam scores (moderate positive correlation)
@@ -42,17 +43,17 @@
4243
exam_scores = np.clip(exam_scores, 30, 105)
4344
df = pd.DataFrame({"study_hours": study_hours, "exam_scores": exam_scores})
4445

45-
# Plot
46+
# Plot — shape=21 allows theme-adaptive stroke matching PAGE_BG for marker definition
4647
plot = (
4748
ggplot(df, aes(x="study_hours", y="exam_scores"))
48-
+ geom_point(color=BRAND, size=6, alpha=0.7, stroke=0.6)
49+
+ geom_point(shape=21, fill=BRAND, color=PAGE_BG, size=6, alpha=0.75, stroke=0.8)
4950
+ labs(x="Study Hours per Day", y="Exam Score (points)", title="scatter-basic · letsplot · anyplot.ai")
5051
+ ggsize(1600, 900)
5152
+ theme_minimal()
5253
+ theme(
5354
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
5455
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
55-
panel_grid_major=element_line(color=GRID, size=0.3),
56+
panel_grid_major=element_line(color=GRID, size=0.4),
5657
panel_grid_minor=element_blank(),
5758
axis_title=element_text(size=20, color=INK),
5859
axis_text=element_text(size=16, color=INK_SOFT),

plots/scatter-basic/metadata/python/letsplot.yaml

Lines changed: 68 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,52 @@ library: letsplot
22
language: python
33
specification_id: scatter-basic
44
created: '2025-12-10T20:55:10Z'
5-
updated: '2026-04-23T19:25:04Z'
5+
updated: '2026-04-23T22:09:54Z'
66
generated_by: claude-opus
7-
workflow_run: 24853816154
7+
workflow_run: 24861090813
88
issue: 611
99
python_version: 3.14.4
1010
library_version: 4.9.0
1111
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-light.png
1212
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-dark.png
1313
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-light.html
1414
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/letsplot/plot-dark.html
15-
quality_score: 88
15+
quality_score: 89
1616
review:
1717
strengths:
18-
- 'Perfect spec compliance: all required features present, correct title format,
19-
appropriate single-series handling with no legend'
20-
- 'Excellent theme implementation: both renders adapt correctly with proper background/text/chrome
21-
token mapping'
22-
- Clean, readable code with explicit font sizing (24pt title, 20pt labels, 16pt
23-
ticks) and reproducible data generation via np.random.seed(42)
24-
- Generates interactive HTML output alongside PNG — leverages a key lets-plot advantage
18+
- 'Theme-adaptive chrome is fully correct: PAGE_BG, INK, INK_SOFT tokens applied
19+
to all non-data elements in both light and dark renders'
20+
- Shape=21 with PAGE_BG stroke creates subtle marker definition that adapts to theme
21+
— sophisticated approach
22+
- Pre-blended GRID color avoids alpha transparency issues in lets-plot element_line
23+
- All font sizes explicitly set (title=24, axis=20, ticks=16) meeting DPI-based
24+
requirements
25+
- Seed set, axis labels descriptive with units, clean KISS structure, HTML + PNG
26+
export
27+
- Data scenario (study hours vs exam scores) is realistic, neutral, and correctly
28+
shows moderate positive correlation
2529
weaknesses:
26-
- 'Grid uses full-opacity INK colors (#1A1A17 light / #F0EFE8 dark) instead of the
27-
recommended ~10% opacity rgba; this makes the dark render grid more visible than
28-
ideal'
29-
- No visual hierarchy or emphasis — the scatter cloud is presented uniformly with
30-
no focal point, trend line, or emphasis on notable data points
31-
- Design aesthetics stay at polished-default level; lacks distinctive styling touches
32-
(e.g., theme-adaptive marker stroke color, trend line) that would elevate it above
33-
a standard library output
30+
- 'DE-03 LOW: Data is displayed but no visual hierarchy or emphasis — viewer must
31+
find their own story. Adding geom_smooth() with a subtle trend line would create
32+
a focal point and guide the viewer to the correlation insight'
33+
- 'DE-01 MODERATE: Design is above defaults but not ''strong design''. Adding a
34+
geom_smooth trend line (with matching INK_SOFT color and high transparency) and
35+
perhaps a subtitle noting the correlation would push this to strong design territory'
36+
- 'LM-02 LOW: Generic ggplot2 grammar with no lets-plot-distinctive features. geom_smooth()
37+
is a natural lets-plot feature that would add storytelling value; theme-native
38+
faceting or using lets_plot tooltips (HTML) are other options'
3439
image_description: |-
3540
Light render (plot-light.png):
3641
Background: Warm off-white #FAF8F1 — correct, not pure white
37-
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.
38-
Data: 180 scatter points in brand green #009E73, alpha=0.7, size=6. Clear positive correlation visible.
39-
Legibility verdict: PASS — all text readable against light background, no light-on-light failures
42+
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
43+
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
44+
Legibility verdict: PASS — all text clearly readable against warm off-white background
4045
4146
Dark render (plot-dark.png):
4247
Background: Warm near-black #1A1A17 — correct, not pure black
43-
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).
44-
Data: 180 scatter points in identical brand green #009E73unchanged from light render, visible and distinguishable against dark background.
45-
Legibility verdict: PASS — all text readable against dark background, no dark-on-dark failures detected
48+
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
49+
Data: Same 180 #009E73 green pointsidentical color to light render, only chrome flipped — correct Okabe-Ito palette consistency
50+
Legibility verdict: PASS — all text readable; no dark-on-dark failures; brand green #009E73 clearly visible on near-black surface
4651
criteria_checklist:
4752
visual_quality:
4853
score: 30
@@ -53,71 +58,72 @@ review:
5358
score: 8
5459
max: 8
5560
passed: true
56-
comment: Title 24pt bold, axis labels 20pt, ticks 16pt — all explicitly set
57-
and readable in both themes
61+
comment: 'All font sizes explicitly set: title=24, axis=20, ticks=16 — perfect
62+
DPI-based sizing'
5863
- id: VQ-02
5964
name: No Overlap
6065
score: 6
6166
max: 6
6267
passed: true
63-
comment: No text or label collisions
68+
comment: No text or element overlap in either render
6469
- id: VQ-03
6570
name: Element Visibility
6671
score: 6
6772
max: 6
6873
passed: true
69-
comment: size=6, alpha=0.7 well-adapted for 180 points; markers clearly visible
74+
comment: 180 points, size=6, alpha=0.75, shape=21 with stroke — well-adapted
75+
to density
7076
- id: VQ-04
7177
name: Color Accessibility
7278
score: 2
7379
max: 2
7480
passed: true
75-
comment: 'Okabe-Ito #009E73 provides good contrast on both surfaces; CVD-safe'
81+
comment: 'Single series in Okabe-Ito #009E73 CVD-safe'
7682
- id: VQ-05
7783
name: Layout & Canvas
7884
score: 4
7985
max: 4
8086
passed: true
81-
comment: 4800x2700 landscape, good margins, plot fills canvas well
87+
comment: Plot fills canvas well with balanced margins
8288
- id: VQ-06
8389
name: Axis Labels & Title
8490
score: 2
8591
max: 2
8692
passed: true
87-
comment: Study Hours per Day and Exam Score (points) — descriptive with units
93+
comment: 'Both axes descriptive with units: ''Study Hours per Day'', ''Exam
94+
Score (points)'''
8895
- id: VQ-07
8996
name: Palette Compliance
9097
score: 2
9198
max: 2
9299
passed: true
93-
comment: 'First series is #009E73; backgrounds correct (#FAF8F1 / #1A1A17);
94-
chrome adapts correctly in both renders'
100+
comment: 'Single series uses brand #009E73; backgrounds #FAF8F1 (light) and
101+
#1A1A17 (dark); theme-correct chrome in both renders'
95102
design_excellence:
96-
score: 10
103+
score: 11
97104
max: 20
98105
items:
99106
- id: DE-01
100107
name: Aesthetic Sophistication
101-
score: 4
108+
score: 5
102109
max: 8
103-
passed: false
104-
comment: Well-configured and clean but not exceptional; polished library default
105-
rather than distinctive design
110+
passed: true
111+
comment: Above defaults with theme-adaptive stroke, warm backgrounds, and
112+
pre-blended grid — not yet 'strong design'
106113
- id: DE-02
107114
name: Visual Refinement
108115
score: 4
109116
max: 6
110-
passed: false
111-
comment: Tick marks removed, minor grid suppressed, axis lines styled. Grid
112-
major lines use full-opacity INK color instead of ~10% rgba — dark render
113-
grid more visible than ideal
117+
passed: true
118+
comment: Minor grid removed, axis ticks removed, subtle grid lines — good
119+
refinement
114120
- id: DE-03
115121
name: Data Storytelling
116122
score: 2
117123
max: 6
118124
passed: false
119-
comment: Data displayed clearly, positive correlation apparent, but no visual
120-
hierarchy, emphasis, trend line, or focal point
125+
comment: Correlation visible but no visual hierarchy or emphasis — no trend
126+
line, no focal point
121127
spec_compliance:
122128
score: 15
123129
max: 15
@@ -127,27 +133,26 @@ review:
127133
score: 5
128134
max: 5
129135
passed: true
130-
comment: Correct scatter via geom_point()
136+
comment: Correct scatter plot
131137
- id: SC-02
132138
name: Required Features
133139
score: 4
134140
max: 4
135141
passed: true
136-
comment: Alpha transparency, axis labels, title, grid lines, appropriate point
137-
sizing — all present
142+
comment: Transparency, axis labels, title, grid — all present
138143
- id: SC-03
139144
name: Data Mapping
140145
score: 3
141146
max: 3
142147
passed: true
143-
comment: X/Y correctly assigned; all 180 points visible
148+
comment: X=study hours (independent), Y=exam scores (dependent), r~0.7 correlation
144149
- id: SC-04
145150
name: Title & Legend
146151
score: 3
147152
max: 3
148153
passed: true
149-
comment: Title exactly 'scatter-basic · letsplot · anyplot.ai'; no legend
150-
appropriate for single series
154+
comment: Title 'scatter-basic · letsplot · anyplot.ai' correct; no legend
155+
(single series — appropriate)
151156
data_quality:
152157
score: 15
153158
max: 15
@@ -157,22 +162,19 @@ review:
157162
score: 6
158163
max: 6
159164
passed: true
160-
comment: Clear positive correlation with realistic scatter/noise, outliers
161-
present, full range visible
165+
comment: 'Covers full scatter range: spread, correlation, outliers'
162166
- id: DQ-02
163167
name: Realistic Context
164168
score: 5
165169
max: 5
166170
passed: true
167-
comment: Study hours vs exam scores — real, relatable, neutral educational
168-
scenario
171+
comment: Study hours vs exam scores — real, neutral, educational scenario
169172
- id: DQ-03
170173
name: Appropriate Scale
171174
score: 4
172175
max: 4
173176
passed: true
174-
comment: Hours 1-10/day and scores 30-105 are realistic; moderate r~0.7 correlation
175-
as specified
177+
comment: 1–10 hours/day realistic; scores 30–105 (labeled as points, not %)
176178
code_quality:
177179
score: 10
178180
max: 10
@@ -182,20 +184,19 @@ review:
182184
score: 3
183185
max: 3
184186
passed: true
185-
comment: 'Flat linear code: imports → tokens → data → plot → save; no functions
186-
or classes'
187+
comment: Imports → data → plot → save, no functions/classes
187188
- id: CQ-02
188189
name: Reproducibility
189190
score: 2
190191
max: 2
191192
passed: true
192-
comment: np.random.seed(42) set
193+
comment: np.random.seed(42)
193194
- id: CQ-03
194195
name: Clean Imports
195196
score: 2
196197
max: 2
197198
passed: true
198-
comment: All imports used; element_blank used in two theme overrides
199+
comment: All imports used
199200
- id: CQ-04
200201
name: Code Elegance
201202
score: 2
@@ -207,7 +208,7 @@ review:
207208
score: 1
208209
max: 1
209210
passed: true
210-
comment: Saves plot-{THEME}.png and plot-{THEME}.html; current lets-plot API
211+
comment: Saves plot-{THEME}.png and plot-{THEME}.html with scale=3
211212
library_mastery:
212213
score: 8
213214
max: 10
@@ -217,16 +218,15 @@ review:
217218
score: 5
218219
max: 5
219220
passed: true
220-
comment: 'Expert use of ggplot grammar: aes(), geom_point(), labs(), ggsize(),
221-
theme_minimal() + theme() override, ggsave(scale=3)'
221+
comment: 'Expert ggplot2 grammar: ggplot+geom_point+labs+theme, ggsize, ggsave
222+
with scale'
222223
- id: LM-02
223224
name: Distinctive Features
224225
score: 3
225226
max: 5
226-
passed: false
227-
comment: Uses lets-plot-specific ggsize(), scale=3 export for pixel-density,
228-
and HTML export — all distinctive to lets-plot, but no use of advanced lets-plot-only
229-
features like geom_smooth with confidence interval or built-in interactivity
227+
passed: true
228+
comment: shape=21 fill/stroke paradigm and HTML export are lets-plot features,
229+
but no geom_smooth or truly distinctive lets-plot capabilities
230230
verdict: REJECTED
231231
impl_tags:
232232
dependencies: []
@@ -237,3 +237,4 @@ impl_tags:
237237
dataprep: []
238238
styling:
239239
- alpha-blending
240+
- edge-highlighting

0 commit comments

Comments
 (0)