Skip to content

Commit b34ca57

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

2 files changed

Lines changed: 229 additions & 196 deletions

File tree

Lines changed: 55 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,83 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
sankey-basic: Basic Sankey Diagram
3-
Library: plotly 6.5.0 | Python 3.13.11
4-
Quality: 93/100 | Created: 2025-12-23
3+
Library: plotly 6.7.0 | Python 3.13.13
4+
Quality: 90/100 | Updated: 2026-04-30
55
"""
66

7+
import os
8+
79
import plotly.graph_objects as go
810

911

10-
# Data - Energy flow from sources to end-use sectors (in TWh)
12+
# Theme tokens
13+
THEME = os.getenv("ANYPLOT_THEME", "light")
14+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
15+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
16+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
17+
18+
# Okabe-Ito palette for source nodes (positions 1-4)
19+
OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7"]
20+
SOURCE_RGBA = ["rgba(0,158,115,0.4)", "rgba(213,94,0,0.4)", "rgba(0,114,178,0.4)", "rgba(204,121,167,0.4)"]
21+
22+
# Data - Energy flow from sources to sectors (TWh)
1123
sources = ["Coal", "Natural Gas", "Nuclear", "Renewables"]
1224
targets = ["Residential", "Commercial", "Industrial", "Transportation"]
13-
14-
# Node labels (sources first, then targets)
1525
labels = sources + targets
1626

17-
# Define flows: (source_index, target_index, value)
18-
# Indices: Coal=0, Gas=1, Nuclear=2, Renewables=3
19-
# Residential=4, Commercial=5, Industrial=6, Transportation=7
2027
flows = [
21-
# Coal flows
22-
(0, 4, 5), # Coal -> Residential
23-
(0, 5, 8), # Coal -> Commercial
24-
(0, 6, 25), # Coal -> Industrial
25-
# Natural Gas flows
26-
(1, 4, 22), # Gas -> Residential
27-
(1, 5, 18), # Gas -> Commercial
28-
(1, 6, 15), # Gas -> Industrial
29-
(1, 7, 3), # Gas -> Transportation
30-
# Nuclear flows
31-
(2, 4, 12), # Nuclear -> Residential
32-
(2, 5, 10), # Nuclear -> Commercial
33-
(2, 6, 8), # Nuclear -> Industrial
34-
# Renewables flows
35-
(3, 4, 8), # Renewables -> Residential
36-
(3, 5, 6), # Renewables -> Commercial
37-
(3, 6, 5), # Renewables -> Industrial
38-
(3, 7, 4), # Renewables -> Transportation
28+
(0, 4, 5),
29+
(0, 5, 8),
30+
(0, 6, 25),
31+
(1, 4, 22),
32+
(1, 5, 18),
33+
(1, 6, 15),
34+
(1, 7, 3),
35+
(2, 4, 12),
36+
(2, 5, 10),
37+
(2, 6, 8),
38+
(3, 4, 8),
39+
(3, 5, 6),
40+
(3, 6, 5),
41+
(3, 7, 4),
3942
]
4043

4144
source_indices = [f[0] for f in flows]
4245
target_indices = [f[1] for f in flows]
4346
values = [f[2] for f in flows]
4447

45-
# Colors for source nodes (Python Blue variations and Yellow)
46-
node_colors = [
47-
"#306998", # Coal - Python Blue
48-
"#4A90C2", # Natural Gas - Light Blue
49-
"#FFD43B", # Nuclear - Python Yellow
50-
"#7AB648", # Renewables - Green
51-
"#8FA8BD", # Residential
52-
"#A3B8CC", # Commercial
53-
"#B8C9DB", # Industrial
54-
"#CCD9E8", # Transportation
55-
]
56-
57-
# Link colors with transparency (based on source)
58-
link_colors = [
59-
"rgba(48, 105, 152, 0.5)"
60-
if s == 0
61-
else "rgba(74, 144, 194, 0.5)"
62-
if s == 1
63-
else "rgba(255, 212, 59, 0.5)"
64-
if s == 2
65-
else "rgba(122, 182, 72, 0.5)"
66-
for s in source_indices
67-
]
48+
# Source nodes use Okabe-Ito colors; target nodes use INK_SOFT
49+
node_colors = OKABE_ITO + [INK_SOFT] * 4
50+
link_colors = [SOURCE_RGBA[s] for s in source_indices]
6851

69-
# Create Sankey diagram
52+
# Plot
7053
fig = go.Figure(
7154
data=[
7255
go.Sankey(
73-
node=dict(pad=25, thickness=35, line=dict(color="white", width=2), label=labels, color=node_colors),
74-
link=dict(source=source_indices, target=target_indices, value=values, color=link_colors),
56+
node={
57+
"pad": 25,
58+
"thickness": 35,
59+
"line": {"color": PAGE_BG, "width": 1},
60+
"label": labels,
61+
"color": node_colors,
62+
},
63+
link={"source": source_indices, "target": target_indices, "value": values, "color": link_colors},
7564
)
7665
]
7766
)
7867

79-
# Update layout for 4800x2700 px output
8068
fig.update_layout(
81-
title=dict(
82-
text="Energy Distribution · sankey-basic · plotly · pyplots.ai", font=dict(size=36), x=0.5, xanchor="center"
83-
),
84-
font=dict(size=22),
85-
template="plotly_white",
86-
margin=dict(l=80, r=80, t=120, b=60),
69+
title={
70+
"text": "Energy Distribution · sankey-basic · plotly · anyplot.ai",
71+
"font": {"size": 28, "color": INK},
72+
"x": 0.5,
73+
"xanchor": "center",
74+
},
75+
paper_bgcolor=PAGE_BG,
76+
plot_bgcolor=PAGE_BG,
77+
font={"size": 22, "color": INK},
78+
margin={"l": 80, "r": 80, "t": 120, "b": 60},
8779
)
8880

89-
# Save outputs
90-
fig.write_image("plot.png", width=1600, height=900, scale=3)
91-
fig.write_html("plot.html")
81+
# Save
82+
fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
83+
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")

0 commit comments

Comments
 (0)