Skip to content

Commit 280f1fd

Browse files
feat(seaborn): implement scatter-basic (#5319)
## Implementation: `scatter-basic` - python/seaborn Implements the **python/seaborn** version of `scatter-basic`. **File:** `plots/scatter-basic/implementations/python/seaborn.py` **Parent Issue:** #611 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24859691916)* --------- 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 5c1c5db commit 280f1fd

2 files changed

Lines changed: 92 additions & 90 deletions

File tree

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

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

77
import os
@@ -19,23 +19,18 @@
1919
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
2020
BRAND = "#009E73" # Okabe-Ito position 1
2121

22-
# Data — study hours vs exam scores with realistic correlation and variety
22+
# Data — marketing spend vs. quarterly sales revenue (r~0.75)
2323
np.random.seed(42)
24-
n = 150
25-
study_hours = np.random.uniform(1, 10, n)
26-
exam_scores = 12 * study_hours - 0.4 * study_hours**2 + np.random.randn(n) * 7 + 30
24+
n = 220
25+
marketing_spend = np.random.gamma(shape=2.2, scale=9.0, size=n) + 3
26+
sales_revenue = 4.1 * marketing_spend + np.random.normal(0, 18, n) + 15
27+
sales_revenue = np.clip(sales_revenue, 5, None)
2728

28-
# Natural outliers: a few high-effort underperformers and gifted low-study students
29-
exam_scores[0], study_hours[0] = 95, 2.5
30-
exam_scores[5], study_hours[5] = 28, 8.5
31-
exam_scores[10], study_hours[10] = 88, 3.0
32-
exam_scores[140], study_hours[140] = 35, 7.8
33-
exam_scores[145], study_hours[145] = 92, 5.5
34-
35-
df = pd.DataFrame({"Study Hours (per week)": study_hours, "Exam Score (points)": exam_scores})
29+
df = pd.DataFrame({"Marketing Spend ($ thousands)": marketing_spend, "Quarterly Revenue ($ thousands)": sales_revenue})
3630

3731
# Plot
3832
sns.set_theme(
33+
context="talk",
3934
style="ticks",
4035
rc={
4136
"figure.facecolor": PAGE_BG,
@@ -47,32 +42,32 @@
4742
"ytick.color": INK_SOFT,
4843
"grid.color": INK,
4944
"grid.alpha": 0.10,
50-
"font.family": "sans-serif",
51-
"axes.linewidth": 0.8,
45+
"axes.linewidth": 0.9,
46+
"axes.grid": True,
47+
"axes.axisbelow": True,
5248
},
5349
)
5450

5551
fig, ax = plt.subplots(figsize=(16, 9))
5652

5753
sns.scatterplot(
5854
data=df,
59-
x="Study Hours (per week)",
60-
y="Exam Score (points)",
55+
x="Marketing Spend ($ thousands)",
56+
y="Quarterly Revenue ($ thousands)",
6157
ax=ax,
6258
color=BRAND,
63-
s=220,
59+
s=130,
6460
alpha=0.7,
6561
edgecolor=PAGE_BG,
66-
linewidth=0.8,
62+
linewidth=0.9,
6763
)
6864

6965
# Style
70-
ax.set_title("scatter-basic · seaborn · anyplot.ai", fontsize=24, fontweight="medium", color=INK, pad=18)
71-
ax.set_xlabel("Study Hours (per week)", fontsize=20, color=INK)
72-
ax.set_ylabel("Exam Score (points)", fontsize=20, color=INK)
73-
ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT)
74-
ax.grid(True, linewidth=0.8)
75-
ax.set_axisbelow(True)
66+
ax.set_title("scatter-basic · seaborn · anyplot.ai", fontsize=24, fontweight="medium", color=INK, pad=20)
67+
ax.set_xlabel("Marketing Spend ($ thousands)", fontsize=20, color=INK, labelpad=12)
68+
ax.set_ylabel("Quarterly Revenue ($ thousands)", fontsize=20, color=INK, labelpad=12)
69+
ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT, length=0)
70+
ax.margins(x=0.04, y=0.06)
7671
sns.despine(ax=ax)
7772

7873
plt.tight_layout()

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

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ library: seaborn
22
language: python
33
specification_id: scatter-basic
44
created: '2025-12-10T20:55:10Z'
5-
updated: '2026-04-23T19:24:09Z'
5+
updated: '2026-04-23T21:35:58Z'
66
generated_by: claude-opus
7-
workflow_run: 24853787271
7+
workflow_run: 24859691916
88
issue: 611
99
python_version: 3.14.4
1010
library_version: 0.13.2
@@ -15,34 +15,35 @@ preview_html_dark: null
1515
quality_score: 85
1616
review:
1717
strengths:
18-
- 'Full theme-adaptive implementation: both renders are clean, readable, and visually
19-
consistent with Okabe-Ito palette and correct background tokens'
20-
- 'Excellent code quality: reproducible, KISS structure, clean imports, correct
21-
output naming (plot-{THEME}.png)'
22-
- edgecolor=PAGE_BG on markers is a thoughtful technique that adds visual separation
23-
in the dense cluster region
24-
- 'Spec compliance is perfect: correct scatter type, all required features, proper
25-
title format, appropriate omission of single-series legend'
18+
- Perfect spec compliance and data quality — marketing spend vs. revenue scenario
19+
with realistic right-skewed distribution and natural noise
20+
- Excellent code quality and theme adaptation — all chrome tokens correctly wired
21+
through sns.set_theme rc params; both renders pass legibility checks
22+
- 'Good visual refinements: sns.despine removes top/right spines, tick-length=0,
23+
edgecolor=PAGE_BG for marker definition, subtle grid at alpha=0.10'
2624
weaknesses:
27-
- Marker size s=220 is 2-4x larger than the recommended 50-100 for 150 data points;
28-
visible overlap in dense 3-5 hour cluster
29-
- 'DE-03 default (2/6): deliberately inserted outliers are indistinguishable from
30-
regular data; no regression line or visual emphasis tells a richer story'
31-
- 'LM-02 low (2/5): seaborn''s distinctive scatter strength is built-in statistical
32-
overlays (sns.regplot with CI band) — not used here'
33-
- Exam scores reach 125, slightly ambiguous for a context implying a 0-100 scale
25+
- 'DE-03 (2/6): No visual storytelling — positive correlation is the insight but
26+
nothing guides the viewer toward it; a regression/trend line or correlation annotation
27+
would make the story immediately legible'
28+
- 'DE-01 (4/8): Single-color scatter with no secondary encoding is minimal viable
29+
design; adding a regression line or marginal distributions would push beyond configured-defaults
30+
territory'
31+
- 'LM-02 (2/5): Seaborn''s most distinctive scatter feature (sns.regplot adds trend
32+
line + CI band in one call; sns.jointplot adds marginal distributions) is unused'
33+
- 'VQ-03 (5/6): Marker size s=130 is above recommended s=50-100 for 220 points —
34+
reducing to ~90 with alpha=0.65 would reduce clutter in the dense region'
3435
image_description: |-
3536
Light render (plot-light.png):
36-
Background: Warm off-white (~#FAF8F1), not pure white — correct theme surface
37-
Chrome: Title "scatter-basic · seaborn · anyplot.ai" in medium-weight dark text (readable); axis labels "Study Hours (per week)" and "Exam Score (points)" in dark INK color (readable); tick labels in softer INK_SOFT tone (readable); subtle grid lines on both axes at low opacity
38-
Data: 150 scatter points in #009E73 (brand green, Okabe-Ito position 1); marker size s=220 with alpha=0.7 and PAGE_BG edge color creating visible separation; clear positive correlation from lower-left to upper-right; deliberate outliers visible (low-study high-scorers and high-study low-scorers)
39-
Legibility verdict: PASS
37+
Background: Warm off-white #FAF8F1 — correctly themed, not pure white
38+
Chrome: Title "scatter-basic · seaborn · anyplot.ai" in dark ink, clearly readable; axis labels "Marketing Spend ($ thousands)" and "Quarterly Revenue ($ thousands)" in dark ink at appropriate size; tick labels in muted dark gray (INK_SOFT), all clearly readable
39+
Data: ~220 teal-green scatter points in #009E73 (Okabe-Ito position 1); markers have PAGE_BG edge for definition; clear positive correlation visible; mild overlap in the dense lower-left region
40+
Legibility verdict: PASS — all text clearly readable against warm off-white background; no light-on-light issues
4041
4142
Dark render (plot-dark.png):
42-
Background: Warm near-black (~#1A1A17), not pure black — correct theme surface
43-
Chrome: Title, axis labels, and tick labels all rendered in light cream/off-white (INK #F0EFE8 / INK_SOFT #B8B7B0) — clearly readable against the dark surface; no dark-on-dark failures detected; grid lines remain subtle
44-
Data: Data point colors are identical to light render (#009E73) — only chrome flips; marker edge color maps to #1A1A17 (PAGE_BG for dark theme) which reduces visual separation vs light render but does not cause readability issues
45-
Legibility verdict: PASS
43+
Background: Near-black #1A1A17 — correctly themed, not pure black
44+
Chrome: Title in light text clearly readable; axis labels and tick labels in light/muted-light text — all readable against dark background; no dark-on-dark failures detected
45+
Data: #009E73 teal-green scatter points are identical in color to light render — only chrome has flipped; data colors consistent across themes
46+
Legibility verdict: PASS — all text clearly readable against near-black background; no dark-on-dark failures
4647
criteria_checklist:
4748
visual_quality:
4849
score: 29
@@ -53,47 +54,47 @@ review:
5354
score: 8
5455
max: 8
5556
passed: true
56-
comment: Title 24pt, labels 20pt, ticks 16pt all explicitly set; readable
57-
in both themes
57+
comment: Title 24pt, labels 20pt, ticks 16pt explicitly set; both renders
58+
fully legible
5859
- id: VQ-02
5960
name: No Overlap
6061
score: 6
6162
max: 6
6263
passed: true
63-
comment: Tick labels well-spaced, no text collisions
64+
comment: No text collisions; well-spaced axes and title
6465
- id: VQ-03
6566
name: Element Visibility
6667
score: 5
6768
max: 6
6869
passed: true
69-
comment: s=220 is 2-4x larger than 50-100 guideline for 150 points; edgecolor
70-
helps but dense 3-5hr cluster shows overlap
70+
comment: s=130 slightly above recommended s=50-100 for 220 points; moderate
71+
overlap in dense lower-left; edgecolor mitigates
7172
- id: VQ-04
7273
name: Color Accessibility
7374
score: 2
7475
max: 2
7576
passed: true
76-
comment: 'Single series #009E73 with sufficient contrast on both surfaces;
77-
CVD-safe Okabe-Ito'
77+
comment: Single Okabe-Ito color with alpha=0.7; CVD-safe, no red-green issue
7878
- id: VQ-05
7979
name: Layout & Canvas
8080
score: 4
8181
max: 4
8282
passed: true
83-
comment: 16:9 canvas well-utilized, balanced margins, no cutoff
83+
comment: Plot fills 16:9 canvas well; tight_layout + bbox_inches=tight avoids
84+
waste
8485
- id: VQ-06
8586
name: Axis Labels & Title
8687
score: 2
8788
max: 2
8889
passed: true
89-
comment: Descriptive labels with units on both axes
90+
comment: Descriptive labels with units; title matches required format
9091
- id: VQ-07
9192
name: Palette Compliance
9293
score: 2
9394
max: 2
9495
passed: true
95-
comment: 'First series #009E73; light bg ~#FAF8F1, dark bg ~#1A1A17; all chrome
96-
theme-correct'
96+
comment: 'First series is #009E73; backgrounds #FAF8F1 light / #1A1A17 dark;
97+
chrome uses adaptive INK/INK_SOFT tokens'
9798
design_excellence:
9899
score: 10
99100
max: 20
@@ -103,21 +104,23 @@ review:
103104
score: 4
104105
max: 8
105106
passed: false
106-
comment: Well-configured seaborn default; clean but not exceptionally sophisticated
107+
comment: 'Well-configured defaults: brand green, adaptive theme, clean font.
108+
Solid but generic single-color scatter with no design differentiation beyond
109+
compliance'
107110
- id: DE-02
108111
name: Visual Refinement
109112
score: 4
110113
max: 6
111114
passed: false
112-
comment: sns.despine, subtle grid, set_axisbelow, INK_SOFT ticks, marker edge
113-
colorsgood but not fully polished
115+
comment: 'Good: sns.despine, grid alpha=0.10, tick length=0, edgecolor=PAGE_BG,
116+
axes.axisbelow=Truenot quite every detail polished'
114117
- id: DE-03
115118
name: Data Storytelling
116119
score: 2
117120
max: 6
118121
passed: false
119-
comment: Outliers not visually distinguished; no regression line or trend
120-
emphasis; uniform green cloud
122+
comment: Data displayed correctly but not interpreted; no trend line, no emphasis
123+
on the positive correlation; viewer must find the story themselves
121124
spec_compliance:
122125
score: 15
123126
max: 15
@@ -127,49 +130,53 @@ review:
127130
score: 5
128131
max: 5
129132
passed: true
130-
comment: Correct scatter plot
133+
comment: Correct scatter plot via sns.scatterplot
131134
- id: SC-02
132135
name: Required Features
133136
score: 4
134137
max: 4
135138
passed: true
136-
comment: Alpha 0.7, grid lines, axis labels, descriptive title all present
139+
comment: alpha=0.7, grid lines, axis labels, descriptive title, point size
140+
all present
137141
- id: SC-03
138142
name: Data Mapping
139143
score: 3
140144
max: 3
141145
passed: true
142-
comment: X (study hours), Y (exam scores), all 150 points visible
146+
comment: X/Y correctly assigned; all data within canvas; positive correlation
147+
visible
143148
- id: SC-04
144149
name: Title & Legend
145150
score: 3
146151
max: 3
147152
passed: true
148-
comment: Title 'scatter-basic · seaborn · anyplot.ai' correct; no legend for
149-
single-series (appropriate)
153+
comment: Title matches required format; single-series needs no legend — correct
154+
omission
150155
data_quality:
151-
score: 14
156+
score: 15
152157
max: 15
153158
items:
154159
- id: DQ-01
155160
name: Feature Coverage
156161
score: 6
157162
max: 6
158163
passed: true
159-
comment: Positive correlation, variance, and deliberate outliers in both directions
164+
comment: Gamma-distributed spend creates realistic heteroscedasticity; 220
165+
points show full scatter patterns; noise gives realistic variability
160166
- id: DQ-02
161167
name: Realistic Context
162168
score: 5
163169
max: 5
164170
passed: true
165-
comment: Study hours vs exam scores — neutral, real-world, educationally plausible
171+
comment: Marketing Spend vs. Quarterly Revenue is a neutral, real-world business
172+
scenario
166173
- id: DQ-03
167174
name: Appropriate Scale
168-
score: 3
175+
score: 4
169176
max: 4
170177
passed: true
171-
comment: Study hours 1-10/week plausible; exam scores reach 125 which is slightly
172-
ambiguous if 0-100 scale intended
178+
comment: Marketing spend $3-72K, revenue $5-310K — plausible B2B business
179+
values
173180
code_quality:
174181
score: 10
175182
max: 10
@@ -179,51 +186,51 @@ review:
179186
score: 3
180187
max: 3
181188
passed: true
182-
comment: Linear Imports → Data → Plot → Save; no functions or classes
189+
comment: 'Linear flow: imports → tokens → data → plot → style → save; no functions
190+
or classes'
183191
- id: CQ-02
184192
name: Reproducibility
185193
score: 2
186194
max: 2
187195
passed: true
188-
comment: np.random.seed(42) present
196+
comment: np.random.seed(42) set
189197
- id: CQ-03
190198
name: Clean Imports
191199
score: 2
192200
max: 2
193201
passed: true
194-
comment: All 5 imports (os, matplotlib.pyplot, numpy, pandas, seaborn) are
195-
used
202+
comment: All imports (os, matplotlib, numpy, pandas, seaborn) are used
196203
- id: CQ-04
197204
name: Code Elegance
198205
score: 2
199206
max: 2
200207
passed: true
201-
comment: Clean, Pythonic; no over-engineering; no fake functionality
208+
comment: Clean, Pythonic; appropriate complexity for the task
202209
- id: CQ-05
203210
name: Output & API
204211
score: 1
205212
max: 1
206213
passed: true
207-
comment: Saves plot-{THEME}.png with dpi=300, bbox_inches=tight, facecolor=PAGE_BG;
208-
current seaborn API
214+
comment: Saves as plot-{THEME}.png; uses current seaborn 0.13+ API
209215
library_mastery:
210-
score: 7
216+
score: 6
211217
max: 10
212218
items:
213219
- id: LM-01
214220
name: Idiomatic Usage
215-
score: 5
221+
score: 4
216222
max: 5
217223
passed: true
218-
comment: sns.scatterplot (axes-level preferred), sns.set_theme for global
219-
rc, sns.despine — all idiomatic
224+
comment: sns.set_theme with context=talk, axes-level sns.scatterplot, sns.despine
225+
idiomatic seaborn pattern
220226
- id: LM-02
221227
name: Distinctive Features
222228
score: 2
223229
max: 5
224230
passed: false
225-
comment: set_theme and despine are seaborn-specific but basic; sns.regplot
226-
with CI band (the truly distinctive seaborn scatter feature) not used
231+
comment: sns.despine and set_theme context system are seaborn-distinctive,
232+
but core visualization is bare scatter replicable in matplotlib. sns.regplot
233+
statistical overlay unused.
227234
verdict: REJECTED
228235
impl_tags:
229236
dependencies: []

0 commit comments

Comments
 (0)