Skip to content

Commit 1ee898d

Browse files
feat(seaborn): implement andrews-curves (#6819)
## Implementation: `andrews-curves` - python/seaborn Implements the **python/seaborn** version of `andrews-curves`. **File:** `plots/andrews-curves/implementations/python/seaborn.py` **Parent Issue:** #2859 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25918744692)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent f5af918 commit 1ee898d

2 files changed

Lines changed: 220 additions & 156 deletions

File tree

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,39 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
andrews-curves: Andrews Curves for Multivariate Data
3-
Library: seaborn 0.13.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-30
3+
Library: seaborn 0.13.2 | Python 3.13.13
4+
Quality: 92/100 | Updated: 2026-05-15
55
"""
66

7-
import matplotlib.pyplot as plt
8-
import numpy as np
9-
import pandas as pd
10-
import seaborn as sns
7+
import os
8+
import sys
119

1210

13-
# Load iris dataset from seaborn
11+
# Handle import shadowing: remove current directory from path to avoid
12+
# importing local matplotlib.py or seaborn.py instead of the real libraries
13+
cwd = os.path.dirname(os.path.abspath(__file__))
14+
sys.path = [p for p in sys.path if not (p == cwd or p.startswith(cwd + os.sep))]
15+
16+
import matplotlib.pyplot as plt # noqa: E402
17+
import numpy as np # noqa: E402
18+
import pandas as pd # noqa: E402
19+
import seaborn as sns # noqa: E402
20+
21+
22+
# Theme tokens
23+
THEME = os.getenv("ANYPLOT_THEME", "light")
24+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
25+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
26+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
27+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
28+
29+
# Okabe-Ito palette (first series always #009E73)
30+
OKABE_ITO = [
31+
"#009E73", # bluish green (brand)
32+
"#D55E00", # vermillion
33+
"#0072B2", # blue
34+
]
35+
36+
# Data
1437
df = sns.load_dataset("iris")
1538

1639
# Normalize variables to similar scales
@@ -20,15 +43,14 @@
2043

2144
norm_features = [f + "_norm" for f in features]
2245

23-
# Generate t values from -pi to pi
46+
# Generate t values from -π to π
2447
t = np.linspace(-np.pi, np.pi, 200)
2548

2649
# Compute Andrews curves for all observations
27-
# Andrews curve: f(t) = x1/sqrt(2) + x2*sin(t) + x3*cos(t) + x4*sin(2t) + ...
2850
curves_data = []
2951
for idx, row in df.iterrows():
3052
values = row[norm_features].values.astype(float)
31-
# Compute Fourier series for this observation
53+
# Andrews curve: f(t) = x1/sqrt(2) + x2*sin(t) + x3*cos(t) + x4*sin(2t) + ...
3254
curve_vals = np.full_like(t, values[0] / np.sqrt(2))
3355
for i in range(1, len(values)):
3456
if i % 2 == 1:
@@ -41,42 +63,58 @@
4163

4264
curves_df = pd.DataFrame(curves_data)
4365

44-
# Color palette using Python Blue, Yellow, and a third color
45-
colors = {"setosa": "#306998", "versicolor": "#FFD43B", "virginica": "#E74C3C"}
66+
# Theme-adaptive seaborn styling
67+
sns.set_theme(
68+
style="ticks",
69+
rc={
70+
"figure.facecolor": PAGE_BG,
71+
"axes.facecolor": PAGE_BG,
72+
"axes.edgecolor": INK_SOFT,
73+
"axes.labelcolor": INK,
74+
"text.color": INK,
75+
"xtick.color": INK_SOFT,
76+
"ytick.color": INK_SOFT,
77+
"grid.color": INK,
78+
"grid.alpha": 0.10,
79+
"legend.facecolor": ELEVATED_BG,
80+
"legend.edgecolor": INK_SOFT,
81+
},
82+
)
4683

47-
# Create plot
84+
# Plot
4885
fig, ax = plt.subplots(figsize=(16, 9))
49-
sns.set_style("whitegrid")
5086

5187
# Plot Andrews curves using lineplot with grouped data
5288
sns.lineplot(
5389
data=curves_df,
5490
x="t",
5591
y="f(t)",
5692
hue="species",
57-
palette=colors,
93+
palette=OKABE_ITO,
5894
alpha=0.4,
59-
linewidth=1.5,
95+
linewidth=2.5,
6096
units="obs_id",
6197
estimator=None,
6298
ax=ax,
6399
)
64100

65-
# Style the plot
66-
ax.set_xlabel("t", fontsize=20)
67-
ax.set_ylabel("f(t)", fontsize=20)
68-
ax.set_title("andrews-curves · seaborn · pyplots.ai", fontsize=24)
69-
ax.tick_params(axis="both", labelsize=16)
101+
# Style
102+
ax.set_xlabel("t", fontsize=20, color=INK)
103+
ax.set_ylabel("f(t)", fontsize=20, color=INK)
104+
ax.set_title("andrews-curves · seaborn · anyplot.ai", fontsize=24, color=INK)
105+
ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT)
70106

71-
# Set x-axis ticks to show pi values
107+
# Set x-axis ticks to show π values
72108
ax.set_xticks([-np.pi, -np.pi / 2, 0, np.pi / 2, np.pi])
73109
ax.set_xticklabels(["-π", "-π/2", "0", "π/2", "π"], fontsize=16)
74110

75-
# Customize legend
76-
ax.legend(title="Species", fontsize=16, title_fontsize=18, loc="upper right")
111+
# Legend
112+
ax.legend(title="Species", fontsize=16, title_fontsize=18, loc="upper right", framealpha=0.95)
77113

78-
# Subtle grid
79-
ax.grid(True, alpha=0.3, linestyle="--")
114+
# Grid (subtle, solid lines)
115+
ax.grid(True, alpha=0.10, linewidth=0.8, linestyle="-")
116+
ax.spines["top"].set_visible(False)
117+
ax.spines["right"].set_visible(False)
80118

81119
plt.tight_layout()
82-
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
120+
plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG)

0 commit comments

Comments
 (0)