摘要
作为一个原型,我们能够输出一个二维图形。源代码如下所示。我想尝试输出这个三维图形,所以我开始在现有的代码上乱翻,但经过大量的研究后,我感到不知所措。所以我决定冒着被指出缺乏研究的风险,在stackoverflow上发表一个问题。
我想要实现的目标
目前,这是我们要实现的三个主要目标。
- 我们不希望尽可能多地更改Tkenter的UI,因为我们希望覆盖链接并在以后进行比较。
- 使节点的大小与链接的密度成比例地变大。
- 我想从文本文件中读取拓扑信息并输出图形。
有问题的源代码
- 由于是冗余的,所以源代码做了一定程度的删减,所以可能会有一些不自然的地方,请大家理解。
- 输出二维图形的源代码
import networkx as nx
from networkx.algorithms.centrality.betweenness_subset import edge_betweenness_centrality_subset
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import messagebox
import tkinter.filedialog as fd
# Input Window Settings
tki = tk.Tk() # Tk class generation
tki.geometry('350x300') # screen size
tki.title('link') # screen title
# List check button labels
chk_txt = ['Normal network visualization']
chk_bln = {} #Check box ON/OFF status
# Dynamically create and place check buttons
for i in range(len(chk_txt)):
chk_bln[i] = tk.BooleanVar()
chk = tk.Checkbutton(tki,
variable=chk_bln[i],
text=chk_txt[i])
chk.place(x=50,
y=30 + (i * 24))
path = fd.askopenfilename()
# Command to exit
def close_window():
tki.destroy()
# button generation
btn3 = tk.Button(tki,
text = ' decision ')
btn3.place(x = 100 , y = 200)
btn4 = tk.Button(tki,
text = 'exit',
command = close_window)
btn4.place(x = 150 , y = 250)
# Graph Window Settings
# Load a list of edges
G = nx.read_edgelist(path,
nodetype=int)
edge_size = nx.number_of_edges(G) # number of edges
node_size = nx.number_of_nodes(G) # number of nodes
# Figure Layout Determination
pos = nx.spring_layout(G, k=0.8)
degs = dict(G.degree)
# Figure Creation
plt.figure(figsize=(15, 15))
plt.title("graph",
fontsize = 30,
fontweight = 'bold')
# nodes
# Determine nodes size
average_deg = sum(d for n,d in G.degree()) / G.number_of_nodes() #Calculate the average number of hours for the entire network
sizes = [300 * deg * 2 / average_deg for node,deg in G.degree()] #Sized to be proportional to node order
# Drawing Nodes and Labels
nx.draw_networkx_nodes(G,
pos,
node_color = 'w',
edgecolors = "k",
alpha = 0.75,
node_size = sizes,
linewidths = 2)
nx.draw_networkx_labels(G,
pos,
font_size = 10)
# Reading topology information (.txt)
with open(path, "r") as tf:
line = tf.read().split()
ran = int(len(line) / 2)
# Graph Output
# Button click event (set to checked or unchecked)
def btn_click(bln):
for i in range(len(chk_bln)):
chk_bln[i].set(bln)
# How to draw for each event
def while_1(event):
if(chk_bln[0].get() == True):
#Normal link drawing
nx.draw_networkx_edges(G,
pos,
edge_color = 'c')
plt.show()
#Bind function to button
btn3.bind('<Button-1>',while_1)
- 源代码捏合输出一个3D图形
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import networkx as nx
import numpy as np
import tkinter as tk
from tkinter import messagebox
import tkinter.filedialog as fd
# Input Window Settings
#omission
# Generate edge data
with open(path, "r") as tf:
line = tf.read().split()
ran = int(len(line) / 2)
# Create graphs from generated edge data
G = nx.read_edgelist(path,
nodetype=int)
edge_size = nx.number_of_edges(G) # number of edges
node_size = nx.number_of_nodes(G) # number of nodes
# spring_layout algorithm to generate 3D coordinates
pos = nx.spring_layout(G, k = 0.8, dim = 3)
degs = dict(G.degree)
# Conversion from dictionary type to array type
pos_ary = np.array([pos[n] for n in G])
# visualization
fig = plt.figure()
ax = fig.add_subplot(121, projection="3d")
#Set graph title
ax.set_title("3D graph",size=20)
# Dot the position of each node
ax.scatter(
pos_ary[:, 0],
pos_ary[:, 1],
pos_ary[:, 2],
s=50,
)
# Display labels on nodes
for n in G.nodes:
ax.text(*pos[n], n)
# Edge display
for e in G.edges:
node0_pos = pos[e[0]]
node1_pos = pos[e[1]]
xx = [node0_pos[0], node1_pos[0]]
yy = [node0_pos[1], node1_pos[1]]
zz = [node0_pos[2], node1_pos[2]]
ax.plot(xx, yy, zz, c="#aaaaaa")
# Graph Output
# Button click event (set to checked or unchecked)
def btn_click(bln):
for i in range(len(chk_bln)):
chk_bln[i].set(bln)
# How to draw for each event
def while_1(event):
if(chk_bln[0].get() == True):
#Normal link drawing
nx.draw_networkx_edges(G,
pos#_ary[:,2],
#edge_color = 'c'
)
#View the resulting diagram
plt.show()
#Bind function to button
btn3.bind('<Button-1>',while_1)
遇到问题/错误消息
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Program Files/Python36/3D_test2.py", line 106, in while_1
,edge_color = 'c'
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\networkx\drawing\nx_pylab.py", line 684, in draw_networkx_edges
alpha=alpha,
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\matplotlib\collections.py", line 1393, in __init__
self.set_segments(segments)
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\matplotlib\collections.py", line 1408, in set_segments
self._paths = [mpath.Path(_seg) for _seg in _segments]
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\matplotlib\collections.py", line 1408, in <listcomp>
self._paths = [mpath.Path(_seg) for _seg in _segments]
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\matplotlib\path.py", line 132, in __init__
cbook._check_shape((None, 2), vertices=vertices)
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\matplotlib\cbook\__init__.py", line 2304, in _check_shape
f"{k!r} must be {len(target_shape)}D "
ValueError: 'vertices' must be 2D with shape (M, 2). Your input has shape (2, 3).
- 拓扑信息(.txt)
补充信息
Python 3.6.8
网络x 2.5.1
绘制库3.3.4
我们尝试的
enter image description here第106行的“edge_color = 'c'”被注解掉了,因为发生了与上面相同的错误。当使用“pos_ary[n]”时,输出了以下错误语句。
>>> Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Program Files\Python36\3D_test2.py", line 105, in while_1
pos_ary[n]
IndexError: index 21 is out of bounds for axis 0 with size 21
在第105行中,当使用“pos[n]”时,生成另一个错误消息。这与“pos_ary[n-1]"相同。
>>> Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Program Files\Python36\3D_test2.py",
line 105, in while_1
pos[n]#_ary[:,2],
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\networkx\drawing\nx_pylab.py", line 656, in draw_networkx_edges
edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])
File "C:\Users\████\AppData\Roaming\Python\Python36\site-packages\networkx\drawing\nx_pylab.py", line 656, in <listcomp>
edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])
IndexError: index 10 is out of bounds for axis 0 with size 3
1条答案
按热度按时间icomxhvb1#
如果我没理解错你的问题,复选框“正常网络可视化”控制是否绘制边。是这样吗?如果这是你想要做的,你可以在选中复选框时使用你的代码中的边绘制过程:
若要根据节点的度更改节点的大小,请使用
ax.scatter
并根据节点的度更改标记的大小:[ax.scatter(pos_ary[i, 0],pos_ary[i, 1],pos_ary[i, 2],s=sizes[i],color='b',alpha=0.5) for i in range(len(pos_ary))]
下面是完整的代码。UI保持不变,仍然可以从GUI中选择文件:
以下是未选中“正常网络可视化”复选标记时的结果:
如果“正常网络可视化”复选标记打开: