|
1 | | -""" pyplots.ai |
| 1 | +""" anyplot.ai |
2 | 2 | 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 |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import os |
| 8 | + |
7 | 9 | import plotly.graph_objects as go |
8 | 10 |
|
9 | 11 |
|
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) |
11 | 23 | sources = ["Coal", "Natural Gas", "Nuclear", "Renewables"] |
12 | 24 | targets = ["Residential", "Commercial", "Industrial", "Transportation"] |
13 | | - |
14 | | -# Node labels (sources first, then targets) |
15 | 25 | labels = sources + targets |
16 | 26 |
|
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 |
20 | 27 | 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), |
39 | 42 | ] |
40 | 43 |
|
41 | 44 | source_indices = [f[0] for f in flows] |
42 | 45 | target_indices = [f[1] for f in flows] |
43 | 46 | values = [f[2] for f in flows] |
44 | 47 |
|
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] |
68 | 51 |
|
69 | | -# Create Sankey diagram |
| 52 | +# Plot |
70 | 53 | fig = go.Figure( |
71 | 54 | data=[ |
72 | 55 | 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}, |
75 | 64 | ) |
76 | 65 | ] |
77 | 66 | ) |
78 | 67 |
|
79 | | -# Update layout for 4800x2700 px output |
80 | 68 | 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}, |
87 | 79 | ) |
88 | 80 |
|
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