|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | arc-basic: Basic Arc Diagram |
3 | | -Library: pygal 3.1.0 | Python 3.13.11 |
4 | | -Quality: 94/100 | Created: 2025-12-17 |
| 3 | +Library: pygal 3.1.0 | Python 3.14.3 |
| 4 | +Quality: /100 | Updated: 2026-02-23 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import math |
|
39 | 39 |
|
40 | 40 | # Node positions along x-axis (1 to 10 range) |
41 | 41 | x_positions = np.linspace(1, 10, n_nodes) |
42 | | -y_baseline = 1.0 |
| 42 | +y_baseline = 0.5 |
43 | 43 |
|
44 | | -# Build color tuple: Python Blue for all arcs, Python Yellow for nodes |
| 44 | +# Color palette: weight-based blue shades for arcs (lighter=weak, darker=strong) |
| 45 | +arc_blues = {1: "#7BA7C9", 2: "#306998", 3: "#1B3F5C"} |
| 46 | + |
| 47 | +# Build colors tuple: one entry per edge series + node series |
45 | 48 | n_edges = len(edges) |
46 | | -colors = tuple(["#306998"] * n_edges + ["#FFD43B"]) |
| 49 | +colors = tuple([arc_blues[w] for _, _, w in edges] + ["#FFD43B"]) |
47 | 50 |
|
48 | | -# Custom style for the chart |
| 51 | +# Custom style |
49 | 52 | custom_style = Style( |
50 | 53 | background="white", |
51 | 54 | plot_background="white", |
|
59 | 62 | legend_font_size=40, |
60 | 63 | value_font_size=32, |
61 | 64 | stroke_width=3, |
62 | | - opacity=0.65, |
| 65 | + opacity=0.7, |
63 | 66 | opacity_hover=1.0, |
64 | 67 | ) |
65 | 68 |
|
|
79 | 82 | stroke=True, |
80 | 83 | dots_size=0, |
81 | 84 | stroke_style={"width": 3, "linecap": "round"}, |
82 | | - range=(0, 6), |
| 85 | + range=(0, 4.6), |
83 | 86 | xrange=(0, 11), |
84 | | - x_labels=nodes, |
85 | | - x_labels_major_count=n_nodes, |
| 87 | + x_labels=[{"value": float(x_positions[i]), "label": nodes[i]} for i in range(n_nodes)], |
86 | 88 | truncate_label=-1, |
87 | 89 | ) |
88 | 90 |
|
89 | 91 | # Generate arc points for each edge |
90 | | -# Each arc is drawn as a series of points forming a semi-circle |
91 | | -arc_resolution = 30 # Number of points per arc |
| 92 | +arc_resolution = 40 |
92 | 93 |
|
93 | 94 | for start_idx, end_idx, weight in edges: |
94 | 95 | x_start = x_positions[start_idx] |
|
98 | 99 | x_center = (x_start + x_end) / 2 |
99 | 100 | arc_radius = abs(x_end - x_start) / 2 |
100 | 101 |
|
101 | | - # Arc height proportional to the distance between nodes |
| 102 | + # Arc height proportional to node distance |
102 | 103 | distance = abs(end_idx - start_idx) |
103 | 104 | height_scale = 0.4 * distance |
104 | 105 |
|
105 | 106 | # Generate arc points (semi-circle above baseline) |
106 | 107 | arc_points = [] |
107 | 108 | for i in range(arc_resolution + 1): |
108 | | - theta = math.pi * i / arc_resolution # 0 to pi |
| 109 | + theta = math.pi * i / arc_resolution |
109 | 110 | x = x_center - arc_radius * math.cos(theta) |
110 | 111 | y = y_baseline + height_scale * math.sin(theta) |
111 | 112 | arc_points.append((x, y)) |
112 | 113 |
|
113 | | - # Line thickness based on weight |
114 | 114 | chart.add( |
115 | 115 | f"Arc {start_idx}-{end_idx}", |
116 | 116 | arc_points, |
|
120 | 120 | stroke_style={"width": 2 + weight * 2, "linecap": "round"}, |
121 | 121 | ) |
122 | 122 |
|
123 | | -# Add nodes as a separate series (last, so uses Python Yellow) |
124 | | -node_points = [] |
125 | | -for i, name in enumerate(nodes): |
126 | | - x = x_positions[i] |
127 | | - node_points.append({"value": (x, y_baseline), "label": name}) |
128 | | - |
| 123 | +# Add nodes as a separate series (last, uses Python Yellow) |
| 124 | +node_points = [{"value": (float(x_positions[i]), y_baseline), "label": nodes[i]} for i in range(n_nodes)] |
129 | 125 | chart.add("Characters", node_points, stroke=False, dots_size=35) |
130 | 126 |
|
131 | 127 | # Save outputs |
132 | 128 | chart.render_to_file("plot.svg") |
133 | 129 | chart.render_to_png("plot.png") |
134 | 130 |
|
135 | | -# Also save HTML for interactive version |
| 131 | +# Save HTML for interactive version |
136 | 132 | with open("plot.html", "w") as f: |
137 | 133 | f.write( |
138 | 134 | """<!DOCTYPE html> |
|
0 commit comments