Skip to content

Commit 69bf3b8

Browse files
Merge branch 'main' into implementation/step-basic/seaborn
2 parents bddd356 + 2b195f0 commit 69bf3b8

6 files changed

Lines changed: 354 additions & 310 deletions

File tree

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
""" anyplot.ai
22
step-basic: Basic Step Plot
3-
Library: matplotlib 3.10.9 | Python 3.13.13
4-
Quality: 88/100 | Updated: 2026-04-30
3+
Library: matplotlib 3.11.1 | Python 3.13.14
4+
Quality: 90/100 | Updated: 2026-07-25
55
"""
66

77
import os
88

99
import matplotlib.pyplot as plt
1010
import numpy as np
11+
from matplotlib.colors import to_rgba
1112

1213

1314
# Theme tokens
@@ -16,51 +17,77 @@
1617
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
1718
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
1819
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
19-
BRAND = "#009E73" # Okabe-Ito position 1
20+
BRAND = "#009E73" # Imprint palette position 1
2021

2122
# Data - monthly cumulative sales figures
22-
np.random.seed(42)
23-
months = np.arange(1, 13)
2423
month_labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
2524

2625
monthly_sales = np.array([45, 52, 48, 61, 55, 72, 68, 85, 78, 92, 88, 105])
2726
cumulative_sales = np.cumsum(monthly_sales)
27+
edges = np.arange(0, 13) # 12 month-wide steps: edges[i] -> edges[i+1] holds cumulative_sales[i]
28+
29+
# Milestone the running total crosses mid-year, for a data-storytelling callout
30+
milestone = 500
31+
milestone_idx = int(np.argmax(cumulative_sales >= milestone))
2832

2933
# Plot
30-
fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)
34+
fig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)
3135
ax.set_facecolor(PAGE_BG)
3236

33-
# Filled area under the step for visual emphasis
34-
ax.fill_between(months, cumulative_sales, step="post", alpha=0.12, color=BRAND)
35-
36-
# Step line with 'post' style — value applies from current point until next
37-
ax.step(months, cumulative_sales, where="post", linewidth=3, color=BRAND, label="Cumulative Sales")
37+
# ax.stairs is the distinctive step-plot API (matplotlib >=3.4): a single
38+
# StepPatch driven by bin-style edges, used once filled (baseline=0) for the
39+
# area and once outline-only (baseline=None, no bottom edge) for the line.
40+
ax.stairs(cumulative_sales, edges, baseline=0, fill=True, color=BRAND, alpha=0.12)
41+
ax.stairs(cumulative_sales, edges, baseline=None, color=BRAND, linewidth=2.5, label="Cumulative Sales")
3842

39-
# Markers at each data point to highlight discrete change events
43+
# Markers at the start of each step ('post' style: value holds from this point until the next)
44+
# Semi-opaque brand fill (rather than a raw page-background cutout) keeps markers
45+
# prominent against the filled area at small/thumbnail scale in both themes.
4046
ax.scatter(
41-
months, cumulative_sales, s=200, color=PAGE_BG, edgecolors=BRAND, linewidth=2.5, zorder=5, label="Monthly Totals"
47+
edges[:-1],
48+
cumulative_sales,
49+
s=140,
50+
facecolors=to_rgba(BRAND, 0.35),
51+
edgecolors=BRAND,
52+
linewidth=2,
53+
zorder=5,
54+
label="Monthly Totals",
55+
)
56+
57+
# Milestone callout
58+
ax.axhline(milestone, color=INK_SOFT, linewidth=1, linestyle="--", alpha=0.5)
59+
ax.annotate(
60+
f"{milestone}k milestone\nreached in {month_labels[milestone_idx]}",
61+
xy=(edges[milestone_idx], milestone),
62+
xytext=(edges[milestone_idx] - 2.6, milestone + 130),
63+
fontsize=8,
64+
color=INK,
65+
arrowprops={"arrowstyle": "->", "color": INK_SOFT, "linewidth": 1},
66+
bbox={"facecolor": ELEVATED_BG, "edgecolor": INK_SOFT, "boxstyle": "round,pad=0.3", "alpha": 0.9},
4267
)
4368

4469
# Style
45-
ax.set_xlabel("Month", fontsize=20, color=INK)
46-
ax.set_ylabel("Cumulative Sales (thousands $)", fontsize=20, color=INK)
47-
ax.set_title("step-basic · matplotlib · anyplot.ai", fontsize=24, fontweight="medium", color=INK)
70+
ax.set_xlabel("Month", fontsize=10, color=INK)
71+
ax.set_ylabel("Cumulative Sales (thousands $)", fontsize=10, color=INK)
72+
ax.set_title("step-basic · matplotlib · anyplot.ai", fontsize=12, fontweight="medium", color=INK)
4873

49-
ax.set_xticks(months)
74+
ax.set_xlim(0, 12)
75+
ax.set_ylim(0, cumulative_sales.max() * 1.12)
76+
ax.set_xticks(edges[:-1] + 0.5)
5077
ax.set_xticklabels(month_labels)
51-
ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT)
78+
ax.tick_params(axis="both", labelsize=8, colors=INK_SOFT)
5279

5380
ax.spines["top"].set_visible(False)
5481
ax.spines["right"].set_visible(False)
5582
for s in ("left", "bottom"):
5683
ax.spines[s].set_color(INK_SOFT)
5784

58-
ax.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK)
85+
ax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK)
5986

60-
leg = ax.legend(fontsize=16, loc="upper left")
87+
leg = ax.legend(fontsize=8, loc="upper left")
6188
leg.get_frame().set_facecolor(ELEVATED_BG)
6289
leg.get_frame().set_edgecolor(INK_SOFT)
6390
plt.setp(leg.get_texts(), color=INK_SOFT)
6491

6592
plt.tight_layout()
66-
plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG)
93+
plt.savefig(f"plot-{THEME}.png", dpi=400, facecolor=PAGE_BG) # bbox_inches stays default (None)
Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" anyplot.ai
22
step-basic: Basic Step Plot
3-
Library: plotly 6.7.0 | Python 3.13.13
4-
Quality: 89/100 | Created: 2026-04-30
3+
Library: plotly 6.9.0 | Python 3.13.14
4+
Quality: 89/100 | Created: 2026-07-25
55
"""
66

77
import os
@@ -10,14 +10,13 @@
1010
import plotly.graph_objects as go
1111

1212

13-
# Theme tokens
13+
# Theme tokens (Imprint palette — theme-adaptive chrome)
1414
THEME = os.getenv("ANYPLOT_THEME", "light")
1515
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
16-
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
1716
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
1817
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
19-
GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)"
20-
BRAND = "#009E73" # Okabe-Ito position 1
18+
GRID = "rgba(26,26,23,0.15)" if THEME == "light" else "rgba(240,239,232,0.15)"
19+
BRAND = "#009E73" # Imprint palette position 1
2120

2221
# Data - Monthly cumulative sales showing discrete jumps
2322
np.random.seed(42)
@@ -26,6 +25,7 @@
2625

2726
monthly_sales = np.random.randint(15000, 45000, size=12)
2827
cumulative_sales = np.cumsum(monthly_sales)
28+
year_total = int(cumulative_sales[-1])
2929

3030
# Plot
3131
fig = go.Figure()
@@ -35,48 +35,69 @@
3535
x=x,
3636
y=cumulative_sales,
3737
mode="lines+markers",
38-
line={"shape": "hv", "color": BRAND, "width": 4},
39-
marker={"size": 14, "color": BRAND, "line": {"color": PAGE_BG, "width": 2}},
38+
line={"shape": "hv", "color": BRAND, "width": 3},
39+
marker={"size": 11, "color": BRAND, "line": {"color": PAGE_BG, "width": 2}},
40+
fill="tozeroy",
41+
fillcolor="rgba(0,158,115,0.12)",
4042
name="Cumulative Sales",
43+
customdata=months,
44+
hovertemplate="<b>%{customdata}</b><br>Cumulative: $%{y:,.0f}<extra></extra>",
4145
)
4246
)
4347

48+
# Year-total reference line — focal point highlighting the running total
49+
fig.add_hline(y=year_total, line_dash="dot", line_color=INK_SOFT, line_width=1.5, opacity=0.7)
50+
fig.add_annotation(
51+
x=0,
52+
xref="paper",
53+
y=year_total,
54+
yref="y",
55+
xanchor="left",
56+
yanchor="bottom",
57+
yshift=12,
58+
text=f"Year total ${year_total:,.0f}",
59+
showarrow=False,
60+
font={"size": 11, "color": INK_SOFT},
61+
)
62+
4463
# Style
4564
fig.update_layout(
65+
autosize=False,
66+
width=800,
67+
height=450,
4668
paper_bgcolor=PAGE_BG,
4769
plot_bgcolor=PAGE_BG,
4870
font={"color": INK},
4971
title={
50-
"text": "Monthly Cumulative Sales · step-basic · plotly · anyplot.ai",
51-
"font": {"size": 28, "color": INK},
72+
"text": "step-basic · python · plotly · anyplot.ai",
73+
"font": {"size": 16, "color": INK},
5274
"x": 0.5,
5375
"xanchor": "center",
5476
},
5577
xaxis={
56-
"title": {"text": "Month", "font": {"size": 22, "color": INK}},
57-
"tickfont": {"size": 18, "color": INK_SOFT},
78+
"title": {"text": "Month", "font": {"size": 12, "color": INK}},
79+
"tickfont": {"size": 10, "color": INK_SOFT},
5880
"tickmode": "array",
5981
"tickvals": x,
6082
"ticktext": months,
61-
"showgrid": True,
62-
"gridcolor": GRID,
63-
"gridwidth": 1,
83+
"showgrid": False,
6484
"linecolor": INK_SOFT,
65-
"zerolinecolor": INK_SOFT,
85+
"zeroline": False,
6686
},
6787
yaxis={
68-
"title": {"text": "Cumulative Sales ($)", "font": {"size": 22, "color": INK}},
69-
"tickfont": {"size": 18, "color": INK_SOFT},
88+
"title": {"text": "Cumulative Sales ($)", "font": {"size": 12, "color": INK}},
89+
"tickfont": {"size": 10, "color": INK_SOFT},
7090
"showgrid": True,
7191
"gridcolor": GRID,
7292
"gridwidth": 1,
7393
"linecolor": INK_SOFT,
74-
"zerolinecolor": INK_SOFT,
94+
"zeroline": False,
95+
"rangemode": "tozero",
7596
},
7697
showlegend=False,
77-
margin={"l": 100, "r": 50, "t": 100, "b": 80},
98+
margin={"l": 90, "r": 50, "t": 90, "b": 70},
7899
)
79100

80101
# Save
81-
fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
102+
fig.write_image(f"plot-{THEME}.png", width=800, height=450, scale=4)
82103
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")
Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,70 @@
11
""" anyplot.ai
22
step-basic: Basic Step Plot
3-
Library: plotnine 0.15.3 | Python 3.13.13
4-
Quality: 90/100 | Updated: 2026-04-30
3+
Library: plotnine 0.15.7 | Python 3.13.14
4+
Quality: 90/100 | Updated: 2026-07-25
55
"""
66

77
import os
88

99
import pandas as pd
1010
from plotnine import (
1111
aes,
12+
annotate,
13+
element_blank,
1214
element_line,
1315
element_rect,
1416
element_text,
17+
geom_hline,
1518
geom_point,
1619
geom_step,
1720
ggplot,
1821
labs,
22+
scale_x_continuous,
1923
theme,
2024
theme_minimal,
2125
)
2226

2327

2428
THEME = os.getenv("ANYPLOT_THEME", "light")
2529
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
26-
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
2730
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
2831
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
32+
INK_TERTIARY = "#6B6A63" if THEME == "light" else "#A8A79F"
2933

3034
BRAND = "#009E73"
3135
ACCENT = "#C475FD"
3236

33-
# Data - Monthly cumulative sales figures showing discrete jumps
37+
# Data - Monthly cumulative sales figures showing discrete jumps, vs. an annual target
3438
months = list(range(1, 13))
39+
month_labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
3540
cumulative_sales = [12, 12, 27, 27, 45, 58, 58, 73, 89, 89, 105, 120]
41+
target = 100
3642

3743
df = pd.DataFrame({"month": months, "sales": cumulative_sales})
3844

3945
# Plot
4046
plot = (
4147
ggplot(df, aes(x="month", y="sales"))
42-
+ geom_step(color=BRAND, size=1.5, direction="hv")
43-
+ geom_point(color=ACCENT, size=4, stroke=0.5)
44-
+ labs(x="Month", y="Cumulative Sales (thousands)", title="step-basic · plotnine · anyplot.ai")
48+
+ geom_hline(yintercept=target, color=INK_SOFT, size=0.6, linetype="dashed")
49+
+ annotate("text", x=1, y=target + 5, label=f"Annual target: {target}k", color=INK_TERTIARY, size=6, ha="left")
50+
+ geom_step(color=BRAND, size=1.0, direction="hv")
51+
+ geom_point(color=ACCENT, size=2.5, stroke=0.4)
52+
+ scale_x_continuous(breaks=months, labels=month_labels)
53+
+ labs(x="Month", y="Cumulative Sales (thousands)", title="step-basic · python · plotnine · anyplot.ai")
4554
+ theme_minimal()
4655
+ theme(
47-
figure_size=(16, 9),
56+
figure_size=(8, 4.5),
4857
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
4958
panel_background=element_rect(fill=PAGE_BG),
50-
text=element_text(size=14, color=INK),
51-
axis_title=element_text(size=20, color=INK),
52-
axis_text=element_text(size=16, color=INK_SOFT),
53-
plot_title=element_text(size=24, color=INK),
54-
panel_grid_major=element_line(color=INK, size=0.3, alpha=0.10),
55-
panel_grid_minor=element_line(color=INK, size=0.2, alpha=0.05),
59+
text=element_text(size=7, color=INK),
60+
axis_title=element_text(size=10, color=INK),
61+
axis_text=element_text(size=8, color=INK_SOFT),
62+
plot_title=element_text(size=12, color=INK, weight="bold"),
63+
panel_grid_major=element_line(color=INK, size=0.3, alpha=0.15),
64+
panel_grid_minor=element_blank(),
5665
axis_line=element_line(color=INK_SOFT),
5766
)
5867
)
5968

6069
# Save
61-
plot.save(f"plot-{THEME}.png", dpi=300, width=16, height=9, verbose=False)
70+
plot.save(f"plot-{THEME}.png", dpi=400, width=8, height=4.5, units="in", verbose=False)

0 commit comments

Comments
 (0)