Skip to content

Commit 4559177

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

2 files changed

Lines changed: 117 additions & 87 deletions

File tree

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

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
""" anyplot.ai
22
scatter-basic: Basic Scatter Plot
33
Library: plotly 6.7.0 | Python 3.14.4
4-
Quality: 86/100 | Created: 2026-04-23
4+
Quality: 89/100 | Updated: 2026-04-23
55
"""
66

77
import os
88

99
import numpy as np
1010
import plotly.graph_objects as go
11+
from scipy.stats import gaussian_kde
1112

1213

13-
# Theme tokens (see prompts/default-style-guide.md "Theme-adaptive Chrome")
14+
# Theme tokens
1415
THEME = os.getenv("ANYPLOT_THEME", "light")
1516
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
1617
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
@@ -21,19 +22,33 @@
2122

2223
# Data: study hours vs exam scores, moderate positive correlation
2324
np.random.seed(42)
24-
n_students = 160
25+
n_students = 180
2526
study_hours = np.random.uniform(1, 10, n_students)
2627
exam_scores = 45 + study_hours * 5 + np.random.randn(n_students) * 8
2728
exam_scores = np.clip(exam_scores, 0, 100)
2829

30+
# Per-point local density → subtle alpha variation so sparse outliers gain
31+
# presence while dense clusters reveal overlap through transparency.
32+
density = gaussian_kde(np.vstack([study_hours, exam_scores]))(np.vstack([study_hours, exam_scores]))
33+
density_rank = (density - density.min()) / (density.max() - density.min())
34+
point_alpha = 0.90 - 0.35 * density_rank # sparse: 0.90, dense: 0.55
35+
36+
# Percentile rank for richer hover context
37+
score_percentile = np.argsort(np.argsort(exam_scores)) / (n_students - 1) * 100
38+
2939
# Plot
3040
fig = go.Figure(
3141
go.Scatter(
3242
x=study_hours,
3343
y=exam_scores,
3444
mode="markers",
35-
marker={"size": 13, "color": BRAND, "opacity": 0.7, "line": {"width": 1.2, "color": PAGE_BG}},
36-
hovertemplate="Study: %{x:.1f} h<br>Score: %{y:.1f}%<extra></extra>",
45+
marker={"size": 14, "color": BRAND, "opacity": point_alpha, "line": {"width": 1.2, "color": PAGE_BG}},
46+
customdata=np.stack([score_percentile], axis=-1),
47+
hovertemplate=(
48+
"<b>Study Hours</b>: %{x:.1f} h/day<br>"
49+
"<b>Exam Score</b>: %{y:.1f}%<br>"
50+
"<b>Percentile</b>: %{customdata[0]:.0f}<extra></extra>"
51+
),
3752
showlegend=False,
3853
)
3954
)
@@ -58,6 +73,7 @@
5873
"mirror": False,
5974
"range": [0, 11],
6075
"dtick": 2,
76+
"ticksuffix": " h",
6177
},
6278
yaxis={
6379
"title": {"text": "Exam Score (%)", "font": {"size": 22, "color": INK}, "standoff": 12},
@@ -70,14 +86,24 @@
7086
"mirror": False,
7187
"range": [35, 105],
7288
"dtick": 10,
89+
"ticksuffix": "%",
7390
},
7491
paper_bgcolor=PAGE_BG,
7592
plot_bgcolor=PAGE_BG,
76-
font={"color": INK},
77-
margin={"l": 90, "r": 60, "t": 100, "b": 80},
78-
hoverlabel={"bgcolor": ELEVATED_BG, "bordercolor": INK_SOFT, "font": {"color": INK}},
93+
font={"color": INK, "family": "Inter, Helvetica Neue, Arial, sans-serif"},
94+
margin={"l": 100, "r": 70, "t": 110, "b": 90},
95+
hovermode="closest",
96+
hoverlabel={"bgcolor": ELEVATED_BG, "bordercolor": INK_SOFT, "font": {"color": INK, "size": 15}, "align": "left"},
7997
)
8098

8199
# Save
82100
fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
83-
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")
101+
fig.write_html(
102+
f"plot-{THEME}.html",
103+
include_plotlyjs="cdn",
104+
config={
105+
"displaylogo": False,
106+
"modeBarButtonsToRemove": ["lasso2d", "select2d", "autoScale2d"],
107+
"toImageButtonOptions": {"format": "png", "filename": "scatter-basic-plotly"},
108+
},
109+
)

0 commit comments

Comments
 (0)