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
45 changes: 20 additions & 25 deletions plots/scatter-basic/implementations/python/seaborn.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
""" anyplot.ai
scatter-basic: Basic Scatter Plot
Library: seaborn 0.13.2 | Python 3.14.4
Quality: 85/100 | Created: 2026-04-23
Quality: 85/100 | Updated: 2026-04-23
"""

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

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

# Natural outliers: a few high-effort underperformers and gifted low-study students
exam_scores[0], study_hours[0] = 95, 2.5
exam_scores[5], study_hours[5] = 28, 8.5
exam_scores[10], study_hours[10] = 88, 3.0
exam_scores[140], study_hours[140] = 35, 7.8
exam_scores[145], study_hours[145] = 92, 5.5

df = pd.DataFrame({"Study Hours (per week)": study_hours, "Exam Score (points)": exam_scores})
df = pd.DataFrame({"Marketing Spend ($ thousands)": marketing_spend, "Quarterly Revenue ($ thousands)": sales_revenue})

# Plot
sns.set_theme(
context="talk",
style="ticks",
rc={
"figure.facecolor": PAGE_BG,
Expand All @@ -47,32 +42,32 @@
"ytick.color": INK_SOFT,
"grid.color": INK,
"grid.alpha": 0.10,
"font.family": "sans-serif",
"axes.linewidth": 0.8,
"axes.linewidth": 0.9,
"axes.grid": True,
"axes.axisbelow": True,
},
)

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

sns.scatterplot(
data=df,
x="Study Hours (per week)",
y="Exam Score (points)",
x="Marketing Spend ($ thousands)",
y="Quarterly Revenue ($ thousands)",
ax=ax,
color=BRAND,
s=220,
s=130,
alpha=0.7,
edgecolor=PAGE_BG,
linewidth=0.8,
linewidth=0.9,
)

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

plt.tight_layout()
Expand Down
137 changes: 72 additions & 65 deletions plots/scatter-basic/metadata/python/seaborn.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ library: seaborn
language: python
specification_id: scatter-basic
created: '2025-12-10T20:55:10Z'
updated: '2026-04-23T19:24:09Z'
updated: '2026-04-23T21:35:58Z'
generated_by: claude-opus
workflow_run: 24853787271
workflow_run: 24859691916
issue: 611
python_version: 3.14.4
library_version: 0.13.2
Expand All @@ -15,34 +15,35 @@ preview_html_dark: null
quality_score: 85
review:
strengths:
- 'Full theme-adaptive implementation: both renders are clean, readable, and visually
consistent with Okabe-Ito palette and correct background tokens'
- 'Excellent code quality: reproducible, KISS structure, clean imports, correct
output naming (plot-{THEME}.png)'
- edgecolor=PAGE_BG on markers is a thoughtful technique that adds visual separation
in the dense cluster region
- 'Spec compliance is perfect: correct scatter type, all required features, proper
title format, appropriate omission of single-series legend'
- Perfect spec compliance and data quality — marketing spend vs. revenue scenario
with realistic right-skewed distribution and natural noise
- Excellent code quality and theme adaptation — all chrome tokens correctly wired
through sns.set_theme rc params; both renders pass legibility checks
- 'Good visual refinements: sns.despine removes top/right spines, tick-length=0,
edgecolor=PAGE_BG for marker definition, subtle grid at alpha=0.10'
weaknesses:
- Marker size s=220 is 2-4x larger than the recommended 50-100 for 150 data points;
visible overlap in dense 3-5 hour cluster
- 'DE-03 default (2/6): deliberately inserted outliers are indistinguishable from
regular data; no regression line or visual emphasis tells a richer story'
- 'LM-02 low (2/5): seaborn''s distinctive scatter strength is built-in statistical
overlays (sns.regplot with CI band) — not used here'
- Exam scores reach 125, slightly ambiguous for a context implying a 0-100 scale
- 'DE-03 (2/6): No visual storytelling — positive correlation is the insight but
nothing guides the viewer toward it; a regression/trend line or correlation annotation
would make the story immediately legible'
- 'DE-01 (4/8): Single-color scatter with no secondary encoding is minimal viable
design; adding a regression line or marginal distributions would push beyond configured-defaults
territory'
- 'LM-02 (2/5): Seaborn''s most distinctive scatter feature (sns.regplot adds trend
line + CI band in one call; sns.jointplot adds marginal distributions) is unused'
- 'VQ-03 (5/6): Marker size s=130 is above recommended s=50-100 for 220 points —
reducing to ~90 with alpha=0.65 would reduce clutter in the dense region'
image_description: |-
Light render (plot-light.png):
Background: Warm off-white (~#FAF8F1), not pure white — correct theme surface
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
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)
Legibility verdict: PASS
Background: Warm off-white #FAF8F1 — correctly themed, not pure white
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
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
Legibility verdict: PASS — all text clearly readable against warm off-white background; no light-on-light issues

Dark render (plot-dark.png):
Background: Warm near-black (~#1A1A17), not pure black — correct theme surface
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
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
Legibility verdict: PASS
Background: Near-black #1A1A17 — correctly themed, not pure black
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
Data: #009E73 teal-green scatter points are identical in color to light render — only chrome has flipped; data colors consistent across themes
Legibility verdict: PASS — all text clearly readable against near-black background; no dark-on-dark failures
criteria_checklist:
visual_quality:
score: 29
Expand All @@ -53,47 +54,47 @@ review:
score: 8
max: 8
passed: true
comment: Title 24pt, labels 20pt, ticks 16pt all explicitly set; readable
in both themes
comment: Title 24pt, labels 20pt, ticks 16pt explicitly set; both renders
fully legible
- id: VQ-02
name: No Overlap
score: 6
max: 6
passed: true
comment: Tick labels well-spaced, no text collisions
comment: No text collisions; well-spaced axes and title
- id: VQ-03
name: Element Visibility
score: 5
max: 6
passed: true
comment: s=220 is 2-4x larger than 50-100 guideline for 150 points; edgecolor
helps but dense 3-5hr cluster shows overlap
comment: s=130 slightly above recommended s=50-100 for 220 points; moderate
overlap in dense lower-left; edgecolor mitigates
- id: VQ-04
name: Color Accessibility
score: 2
max: 2
passed: true
comment: 'Single series #009E73 with sufficient contrast on both surfaces;
CVD-safe Okabe-Ito'
comment: Single Okabe-Ito color with alpha=0.7; CVD-safe, no red-green issue
- id: VQ-05
name: Layout & Canvas
score: 4
max: 4
passed: true
comment: 16:9 canvas well-utilized, balanced margins, no cutoff
comment: Plot fills 16:9 canvas well; tight_layout + bbox_inches=tight avoids
waste
- id: VQ-06
name: Axis Labels & Title
score: 2
max: 2
passed: true
comment: Descriptive labels with units on both axes
comment: Descriptive labels with units; title matches required format
- id: VQ-07
name: Palette Compliance
score: 2
max: 2
passed: true
comment: 'First series #009E73; light bg ~#FAF8F1, dark bg ~#1A1A17; all chrome
theme-correct'
comment: 'First series is #009E73; backgrounds #FAF8F1 light / #1A1A17 dark;
chrome uses adaptive INK/INK_SOFT tokens'
design_excellence:
score: 10
max: 20
Expand All @@ -103,21 +104,23 @@ review:
score: 4
max: 8
passed: false
comment: Well-configured seaborn default; clean but not exceptionally sophisticated
comment: 'Well-configured defaults: brand green, adaptive theme, clean font.
Solid but generic single-color scatter with no design differentiation beyond
compliance'
- id: DE-02
name: Visual Refinement
score: 4
max: 6
passed: false
comment: sns.despine, subtle grid, set_axisbelow, INK_SOFT ticks, marker edge
colorsgood but not fully polished
comment: 'Good: sns.despine, grid alpha=0.10, tick length=0, edgecolor=PAGE_BG,
axes.axisbelow=Truenot quite every detail polished'
- id: DE-03
name: Data Storytelling
score: 2
max: 6
passed: false
comment: Outliers not visually distinguished; no regression line or trend
emphasis; uniform green cloud
comment: Data displayed correctly but not interpreted; no trend line, no emphasis
on the positive correlation; viewer must find the story themselves
spec_compliance:
score: 15
max: 15
Expand All @@ -127,49 +130,53 @@ review:
score: 5
max: 5
passed: true
comment: Correct scatter plot
comment: Correct scatter plot via sns.scatterplot
- id: SC-02
name: Required Features
score: 4
max: 4
passed: true
comment: Alpha 0.7, grid lines, axis labels, descriptive title all present
comment: alpha=0.7, grid lines, axis labels, descriptive title, point size
all present
- id: SC-03
name: Data Mapping
score: 3
max: 3
passed: true
comment: X (study hours), Y (exam scores), all 150 points visible
comment: X/Y correctly assigned; all data within canvas; positive correlation
visible
- id: SC-04
name: Title & Legend
score: 3
max: 3
passed: true
comment: Title 'scatter-basic · seaborn · anyplot.ai' correct; no legend for
single-series (appropriate)
comment: Title matches required format; single-series needs no legend — correct
omission
data_quality:
score: 14
score: 15
max: 15
items:
- id: DQ-01
name: Feature Coverage
score: 6
max: 6
passed: true
comment: Positive correlation, variance, and deliberate outliers in both directions
comment: Gamma-distributed spend creates realistic heteroscedasticity; 220
points show full scatter patterns; noise gives realistic variability
- id: DQ-02
name: Realistic Context
score: 5
max: 5
passed: true
comment: Study hours vs exam scores — neutral, real-world, educationally plausible
comment: Marketing Spend vs. Quarterly Revenue is a neutral, real-world business
scenario
- id: DQ-03
name: Appropriate Scale
score: 3
score: 4
max: 4
passed: true
comment: Study hours 1-10/week plausible; exam scores reach 125 which is slightly
ambiguous if 0-100 scale intended
comment: Marketing spend $3-72K, revenue $5-310K — plausible B2B business
values
code_quality:
score: 10
max: 10
Expand All @@ -179,51 +186,51 @@ review:
score: 3
max: 3
passed: true
comment: Linear Imports → Data → Plot → Save; no functions or classes
comment: 'Linear flow: imports → tokens → data → plot → style → save; no functions
or classes'
- id: CQ-02
name: Reproducibility
score: 2
max: 2
passed: true
comment: np.random.seed(42) present
comment: np.random.seed(42) set
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
comment: All 5 imports (os, matplotlib.pyplot, numpy, pandas, seaborn) are
used
comment: All imports (os, matplotlib, numpy, pandas, seaborn) are used
- id: CQ-04
name: Code Elegance
score: 2
max: 2
passed: true
comment: Clean, Pythonic; no over-engineering; no fake functionality
comment: Clean, Pythonic; appropriate complexity for the task
- id: CQ-05
name: Output & API
score: 1
max: 1
passed: true
comment: Saves plot-{THEME}.png with dpi=300, bbox_inches=tight, facecolor=PAGE_BG;
current seaborn API
comment: Saves as plot-{THEME}.png; uses current seaborn 0.13+ API
library_mastery:
score: 7
score: 6
max: 10
items:
- id: LM-01
name: Idiomatic Usage
score: 5
score: 4
max: 5
passed: true
comment: sns.scatterplot (axes-level preferred), sns.set_theme for global
rc, sns.despine — all idiomatic
comment: sns.set_theme with context=talk, axes-level sns.scatterplot, sns.despine
idiomatic seaborn pattern
- id: LM-02
name: Distinctive Features
score: 2
max: 5
passed: false
comment: set_theme and despine are seaborn-specific but basic; sns.regplot
with CI band (the truly distinctive seaborn scatter feature) not used
comment: sns.despine and set_theme context system are seaborn-distinctive,
but core visualization is bare scatter replicable in matplotlib. sns.regplot
statistical overlay unused.
verdict: REJECTED
impl_tags:
dependencies: []
Expand Down
Loading