|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | streamgraph-basic: Basic Stream Graph |
3 | | -Library: matplotlib 3.10.8 | Python 3.13.11 |
4 | | -Quality: 92/100 | Created: 2025-12-23 |
| 3 | +Library: matplotlib 3.10.9 | Python 3.13.13 |
| 4 | +Quality: 88/100 | Updated: 2026-05-05 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import matplotlib.pyplot as plt |
8 | 10 | import numpy as np |
| 11 | +from scipy.interpolate import make_interp_spline |
| 12 | + |
| 13 | + |
| 14 | +THEME = os.getenv("ANYPLOT_THEME", "light") |
| 15 | +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" |
| 16 | +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" |
| 17 | +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" |
| 18 | +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
9 | 19 |
|
| 20 | +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9"] |
10 | 21 |
|
11 | | -# Data - Monthly streaming hours by music genre over two years |
12 | 22 | np.random.seed(42) |
13 | 23 |
|
14 | | -# 24 months of data |
15 | 24 | months = np.arange(24) |
16 | 25 | month_labels = [ |
17 | 26 | "Jan'23", |
|
40 | 49 | "Dec'24", |
41 | 50 | ] |
42 | 51 |
|
43 | | -# Generate realistic genre streaming data with trends |
44 | | -# Pop - consistently high, slight growth |
| 52 | +# Monthly streaming hours by music genre — diverse trend patterns |
45 | 53 | pop = 50 + 10 * np.sin(months / 6) + np.random.randn(24) * 3 + months * 0.3 |
46 | | - |
47 | | -# Rock - stable with seasonal variation |
48 | 54 | rock = 35 + 8 * np.cos(months / 4) + np.random.randn(24) * 2 |
49 | | - |
50 | | -# Hip-Hop - growing trend |
51 | 55 | hiphop = 25 + months * 0.8 + 5 * np.sin(months / 3) + np.random.randn(24) * 3 |
52 | | - |
53 | | -# Electronic - summer peaks |
54 | 56 | electronic = 20 + 15 * np.sin((months - 3) / 6 * np.pi) + np.random.randn(24) * 2 |
55 | | - |
56 | | -# Jazz - steady, slight decline |
57 | 57 | jazz = 18 - months * 0.15 + 4 * np.cos(months / 5) + np.random.randn(24) * 1.5 |
| 58 | +classical = 15 + 8 * np.cos(months / 6 * np.pi) + np.random.randn(24) * 1.5 |
58 | 59 |
|
59 | | -# Classical - winter peaks |
60 | | -classical = 15 + 8 * np.cos((months) / 6 * np.pi) + np.random.randn(24) * 1.5 |
61 | | - |
62 | | -# Ensure all values are positive |
63 | | -pop = np.maximum(pop, 5) |
64 | | -rock = np.maximum(rock, 5) |
65 | | -hiphop = np.maximum(hiphop, 5) |
66 | | -electronic = np.maximum(electronic, 5) |
67 | | -jazz = np.maximum(jazz, 5) |
68 | | -classical = np.maximum(classical, 5) |
| 60 | +data_raw = [pop, rock, hiphop, electronic, jazz, classical] |
| 61 | +for arr in data_raw: |
| 62 | + np.maximum(arr, 5, out=arr) |
69 | 63 |
|
70 | | -# Stack the data |
71 | | -data = np.vstack([pop, rock, hiphop, electronic, jazz, classical]) |
72 | 64 | categories = ["Pop", "Rock", "Hip-Hop", "Electronic", "Jazz", "Classical"] |
73 | 65 |
|
74 | | -# Colors - starting with Python Blue/Yellow, then colorblind-safe palette |
75 | | -colors = ["#306998", "#FFD43B", "#E07A5F", "#81B29A", "#F2CC8F", "#3D405B"] |
76 | | - |
77 | | -# Create plot (4800x2700 px) |
78 | | -fig, ax = plt.subplots(figsize=(16, 9)) |
| 66 | +# Cubic spline interpolation → smooth, flowing curves |
| 67 | +months_fine = np.linspace(0, 23, 300) |
| 68 | +data_smooth = np.array([np.maximum(make_interp_spline(months, series, k=3)(months_fine), 1.0) for series in data_raw]) |
79 | 69 |
|
80 | | -# Create streamgraph with symmetric baseline (wiggle for stream-like appearance) |
81 | | -ax.stackplot(months, data, labels=categories, colors=colors, baseline="wiggle", alpha=0.85) |
| 70 | +fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG) |
| 71 | +ax.set_facecolor(PAGE_BG) |
82 | 72 |
|
83 | | -# Styling |
84 | | -ax.set_xlabel("Month", fontsize=20) |
85 | | -ax.set_title("streamgraph-basic · matplotlib · pyplots.ai", fontsize=24) |
| 73 | +ax.stackplot(months_fine, data_smooth, labels=categories, colors=OKABE_ITO, baseline="wiggle", alpha=0.85) |
86 | 74 |
|
87 | | -# X-axis labels |
88 | | -ax.set_xticks(months[::3]) |
89 | | -ax.set_xticklabels([month_labels[i] for i in range(0, 24, 3)], fontsize=16) |
90 | | -ax.tick_params(axis="y", labelsize=16) |
| 75 | +ax.set_xlabel("Month (Jan 2023 – Dec 2024)", fontsize=20, color=INK) |
| 76 | +ax.set_title("streamgraph-basic · matplotlib · anyplot.ai", fontsize=24, color=INK, fontweight="medium") |
91 | 77 |
|
92 | | -# Remove y-axis ticks for cleaner stream appearance (values are relative) |
| 78 | +tick_positions = list(range(0, 24, 3)) |
| 79 | +ax.set_xticks(tick_positions) |
| 80 | +ax.set_xticklabels([month_labels[i] for i in tick_positions], fontsize=16) |
| 81 | +ax.tick_params(axis="x", colors=INK_SOFT, labelcolor=INK_SOFT) |
93 | 82 | ax.set_yticks([]) |
94 | 83 |
|
95 | | -# Add legend |
96 | | -ax.legend(loc="upper left", fontsize=16, framealpha=0.9) |
97 | | - |
98 | | -# Subtle styling - remove top and right spines |
99 | 84 | ax.spines["top"].set_visible(False) |
100 | 85 | ax.spines["right"].set_visible(False) |
101 | 86 | ax.spines["left"].set_visible(False) |
| 87 | +ax.spines["bottom"].set_color(INK_SOFT) |
| 88 | + |
| 89 | +ax.set_xlim(months_fine[0], months_fine[-1]) |
102 | 90 |
|
103 | | -# Set x limits to remove padding |
104 | | -ax.set_xlim(0, 23) |
| 91 | +leg = ax.legend(loc="upper left", fontsize=16, framealpha=0.9) |
| 92 | +leg.get_frame().set_facecolor(ELEVATED_BG) |
| 93 | +leg.get_frame().set_edgecolor(INK_SOFT) |
| 94 | +plt.setp(leg.get_texts(), color=INK_SOFT) |
105 | 95 |
|
106 | 96 | plt.tight_layout() |
107 | | -plt.savefig("plot.png", dpi=300, bbox_inches="tight") |
| 97 | +plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) |
0 commit comments