|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | arc-basic: Basic Arc Diagram |
3 | | -Library: plotly 6.5.0 | Python 3.13.11 |
4 | | -Quality: 91/100 | Created: 2025-12-23 |
| 3 | +Library: plotly 6.5.2 | Python 3.14.3 |
| 4 | +Quality: /100 | Updated: 2026-02-23 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import numpy as np |
|
13 | 13 | n_nodes = len(nodes) |
14 | 14 |
|
15 | 15 | # Edges: pairs of (source_idx, target_idx, weight) |
16 | | -# Demonstrates short-range and long-range connections with varying weights |
17 | 16 | edges = [ |
18 | | - (0, 1, 3), # Alice-Bob (neighbors, strong connection) |
19 | | - (0, 3, 2), # Alice-David (medium distance) |
| 17 | + (0, 1, 3), # Alice-Bob (neighbors, strong) |
| 18 | + (0, 3, 2), # Alice-David |
20 | 19 | (1, 2, 2), # Bob-Carol |
21 | | - (2, 4, 3), # Carol-Eve |
| 20 | + (2, 4, 3), # Carol-Eve (strong) |
22 | 21 | (3, 5, 2), # David-Frank |
23 | 22 | (4, 6, 2), # Eve-Grace |
24 | | - (5, 7, 3), # Frank-Henry |
25 | | - (0, 8, 1), # Alice-Iris (long arc) |
26 | | - (2, 9, 2), # Carol-Jack (long arc) |
27 | | - (1, 4, 2), # Bob-Eve (medium arc) |
28 | | - (3, 7, 1), # David-Henry (long arc) |
| 23 | + (5, 7, 3), # Frank-Henry (strong) |
| 24 | + (0, 8, 1), # Alice-Iris (long, weak) |
| 25 | + (2, 9, 2), # Carol-Jack (long) |
| 26 | + (1, 4, 2), # Bob-Eve |
| 27 | + (3, 7, 1), # David-Henry (long, weak) |
29 | 28 | (6, 9, 2), # Grace-Jack |
30 | 29 | ] |
31 | 30 |
|
32 | 31 | # Node positions along horizontal axis |
33 | 32 | x_positions = np.linspace(0, 10, n_nodes) |
34 | 33 |
|
| 34 | +# Weight-based styling: opacity and width encode connection strength |
| 35 | +arc_styles = { |
| 36 | + 1: {"color": "rgba(48, 105, 152, 0.30)", "width": 2.0}, |
| 37 | + 2: {"color": "rgba(48, 105, 152, 0.55)", "width": 3.0}, |
| 38 | + 3: {"color": "rgba(48, 105, 152, 0.85)", "width": 4.5}, |
| 39 | +} |
| 40 | + |
35 | 41 | # Create figure |
36 | 42 | fig = go.Figure() |
37 | 43 |
|
38 | 44 | # Draw arcs as smooth parabolic curves |
39 | 45 | for src, tgt, weight in edges: |
40 | | - x_src = x_positions[src] |
41 | | - x_tgt = x_positions[tgt] |
42 | | - |
43 | | - # Arc height proportional to distance between nodes |
44 | | - distance = abs(tgt - src) |
45 | | - arc_height = distance * 0.4 |
| 46 | + x_src, x_tgt = x_positions[src], x_positions[tgt] |
| 47 | + arc_height = abs(tgt - src) * 0.45 |
46 | 48 |
|
47 | | - # Create smooth arc using multiple points |
48 | 49 | t = np.linspace(0, 1, 50) |
49 | 50 | x_arc = x_src + t * (x_tgt - x_src) |
50 | | - y_arc = arc_height * 4 * t * (1 - t) # Parabolic arc |
51 | | - |
52 | | - # Line width based on weight |
53 | | - line_width = 2 + weight * 1.5 |
| 51 | + y_arc = arc_height * 4 * t * (1 - t) |
54 | 52 |
|
| 53 | + style = arc_styles[weight] |
55 | 54 | fig.add_trace( |
56 | 55 | go.Scatter( |
57 | 56 | x=x_arc, |
58 | 57 | y=y_arc, |
59 | 58 | mode="lines", |
60 | | - line={"width": line_width, "color": "#306998"}, |
61 | | - opacity=0.6, |
62 | | - hoverinfo="skip", |
| 59 | + line={"width": style["width"], "color": style["color"]}, |
| 60 | + hoverinfo="text", |
| 61 | + hovertext=f"{nodes[src]} — {nodes[tgt]} (weight {weight})", |
63 | 62 | showlegend=False, |
64 | 63 | ) |
65 | 64 | ) |
|
68 | 67 | fig.add_trace( |
69 | 68 | go.Scatter( |
70 | 69 | x=x_positions, |
71 | | - y=[0] * n_nodes, |
| 70 | + y=np.zeros(n_nodes), |
72 | 71 | mode="markers+text", |
73 | | - marker={"size": 24, "color": "#FFD43B", "line": {"width": 3, "color": "#306998"}}, |
| 72 | + marker={"size": 24, "color": "#FFD43B", "line": {"width": 2.5, "color": "#306998"}}, |
74 | 73 | text=nodes, |
75 | 74 | textposition="bottom center", |
76 | | - textfont={"size": 18, "color": "#306998"}, |
77 | | - hovertemplate="%{text}<extra></extra>", |
| 75 | + textfont={"size": 18, "color": "#2a2a2a"}, |
| 76 | + hovertemplate="<b>%{text}</b><extra></extra>", |
78 | 77 | showlegend=False, |
79 | 78 | ) |
80 | 79 | ) |
81 | 80 |
|
82 | | -# Draw horizontal baseline |
83 | | -fig.add_trace( |
84 | | - go.Scatter( |
85 | | - x=[x_positions[0] - 0.3, x_positions[-1] + 0.3], |
86 | | - y=[0, 0], |
87 | | - mode="lines", |
88 | | - line={"width": 3, "color": "#888888"}, |
89 | | - hoverinfo="skip", |
90 | | - showlegend=False, |
91 | | - ) |
| 81 | +# Subtle horizontal baseline |
| 82 | +fig.add_shape( |
| 83 | + type="line", x0=x_positions[0] - 0.3, x1=x_positions[-1] + 0.3, y0=0, y1=0, line={"width": 1.5, "color": "#CCCCCC"} |
92 | 84 | ) |
93 | 85 |
|
94 | 86 | # Layout |
95 | 87 | fig.update_layout( |
96 | | - title={"text": "arc-basic · plotly · pyplots.ai", "font": {"size": 32}, "x": 0.5, "xanchor": "center"}, |
97 | | - xaxis={"showgrid": False, "zeroline": False, "showticklabels": False, "title": None, "range": [-0.5, 10.5]}, |
98 | | - yaxis={ |
99 | | - "showgrid": False, |
100 | | - "zeroline": False, |
101 | | - "showticklabels": False, |
102 | | - "title": None, |
103 | | - "range": [-1.5, 4], |
104 | | - "scaleanchor": "x", |
105 | | - "scaleratio": 0.5, |
| 88 | + title={ |
| 89 | + "text": "arc-basic · plotly · pyplots.ai", |
| 90 | + "font": {"size": 30, "color": "#2a2a2a"}, |
| 91 | + "x": 0.5, |
| 92 | + "xanchor": "center", |
| 93 | + "y": 0.96, |
106 | 94 | }, |
| 95 | + xaxis={"showgrid": False, "zeroline": False, "showticklabels": False, "showline": False, "range": [-0.5, 10.5]}, |
| 96 | + yaxis={"showgrid": False, "zeroline": False, "showticklabels": False, "showline": False, "range": [-0.6, 4.5]}, |
| 97 | + hovermode="closest", |
| 98 | + hoverlabel={"bgcolor": "white", "font_size": 14, "font_color": "#306998"}, |
107 | 99 | template="plotly_white", |
108 | 100 | plot_bgcolor="white", |
109 | | - margin={"l": 50, "r": 50, "t": 100, "b": 80}, |
| 101 | + paper_bgcolor="white", |
| 102 | + margin={"l": 30, "r": 30, "t": 70, "b": 30}, |
110 | 103 | ) |
111 | 104 |
|
112 | 105 | # Save outputs |
|
0 commit comments