import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from matplotlib.patches import FancyArrowPatch
from matplotlib.colors import Normalize, LinearSegmentedColormap
import matplotlib.colors as mcolors
# Load the adjacency matrix and normalize it
matrix = np.loadtxt('abide-aal90/allAdj_nor.txt') / 25
matrix[matrix < 0.3] = 0
# Create a directed graph from the adjacency matrix
G = nx.from_numpy_array(matrix, create_using=nx.DiGraph)
positions = nx.circular_layout(G)
# Create a custom colormap
light_blue = '#9C5FF2'
light_yellow = '#C2C240'
colors = [(0, light_blue), (0.5, light_yellow), (1, light_blue)]
cmap = LinearSegmentedColormap.from_list('custom_cmap', colors)
norm = Normalize(vmin=0, vmax=len(G.nodes()))
# Function to create custom arrows with gradient colors
def plot_arc(u, v, color, ax):
x0 = -(u[1] - v[1]) / (u[0] * v[1] - u[1] * v[0])
y0 = (u[0] - v[0]) / (u[0] * v[1] - u[1] * v[0])
r = np.sqrt(x0 ** 2 + y0 ** 2 - 1)
thetaLim = [np.arctan2(u[1] - y0, u[0] - x0), np.arctan2(v[1] - y0, v[0] - x0)]
if u[0] >= 0 and v[0] >= 0:
theta = np.concatenate([
np.linspace(np.max(thetaLim), np.pi, 50),
np.linspace(-np.pi, np.min(thetaLim), 50)
])
else:
theta = np.linspace(thetaLim[0], thetaLim[1], 100)
x = r * np.cos(theta) + x0
y = r * np.sin(theta) + y0
ax.plot(x, y, color=color, linewidth=1)
# Add arrowhead at the end of the arc
arrow = FancyArrowPatch((x[-2], y[-2]), (x[-1], y[-1]),
connectionstyle=f"arc3,rad=0",
arrowstyle='-|>', mutation_scale=15, color=color, linewidth=1)
ax.add_patch(arrow)
# Generate a list of colors, ensuring that adjacent nodes have different colors
def get_distinct_colors(G, num_colors):
cmap = plt.get_cmap('tab20') # Use a colormap with many distinct colors
colors = [cmap(i / num_colors) for i in range(num_colors)]
return colors
# Get distinct colors for nodes
num_nodes = len(G.nodes())
distinct_colors = get_distinct_colors(G, num_nodes)
# Ensure no adjacent nodes have the same color
color_map = {}
for node in G.nodes():
# Find a color for the node
for color in distinct_colors:
if all(color != color_map.get(neighbor) for neighbor in G.neighbors(node)):
color_map[node] = color
break
# Plot the graph
fig, ax = plt.subplots(figsize=(10, 10))
# Draw nodes with distinct colors
node_colors = [color_map[node] for node in G.nodes()]
nx.draw_networkx_nodes(G, positions, node_size=400, node_color="none", edgecolors=node_colors, linewidths=2, ax=ax)
# Draw custom edges with gradient colors
for (u, v) in G.edges():
start = positions[u]
end = positions[v]
color = node_colors[u]
plot_arc(start, end, color, ax)
# Draw labels for nodes outside the circular layout
radius = np.sqrt(np.sum(np.square(list(positions.values())), axis=1)).max()
offset = 0.07 * radius # Increase the offset value
for node, (x, y) in positions.items():
angle = np.arctan2(y, x)
new_x = x + offset * np.cos(angle)
new_y = y + offset * np.sin(angle)
# Determine vertical alignment based on node's position relative to center
va = 'bottom' if y >= 0 else 'top'
ax.text(new_x, new_y, str(node + 1), fontsize=9, ha='center', va=va, rotation=np.degrees(angle))
# Remove axis and show plot
ax.axis('off')
plt.show()
# plt.savefig('nor.pdf', format='pdf')
python代码:有向圆环图(关系图、连接图、DAG图)
于 2024-06-12 23:27:28 首次发布