Abstract
As a prototype, we were able to output a 2-dimensional graph. The source code is noted below. I wanted to try outputting this graph in three dimensions, so I started messing around with the existing code, but after much research I was at a loss. So I decided to post a question on stackoverflow at the risk of being pointed out as a lack of research.
What I want to achieve
Currently, these are the three main things we want to achieve.
- We do not want to change the UI of Tkenter as much as possible because we want to overwrite the links and make comparisons later.
- Make the size of the node appear larger in proportion to the density of the links.
- I want to read topology information from a text file and output a graph.
Source code in question
*Since it is redundant, the source code has been cut to some extent. Therefore, please understand that there may be some unnatural points.
- Source code to output a 2-dimensional graph
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)
- Source code kneaded to output a 3D a graph
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)
Problem/error message being encountered
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).
- Topology Information(.txt)
1 10
1 11
1 14
1 20
2 9
2 12
2 13
2 15
2 16
3 10
3 11
3 20
4 5
4 8
4 9
5 4
5 9
6 7
6 14
7 6
7 18
8 4
8 11
8 14
8 19
9 2
9 4
9 5
10 1
10 3
11 1
11 3
11 8
11 13
12 2
12 16
13 2
13 11
14 1
14 6
14 8
15 2
15 17
15 21
16 2
16 12
17 15
18 7
18 21
19 8
19 20
20 1
20 3
20 19
20 21
21 15
21 18
21 20
supplementary information
python 3.6.8
networkx 2.5.1
matplotlib 3.3.4
What we tried
If you do not enter anything in the checkbox, the output will be done. enter image description here The "edge_color = 'c'" on line 106 is commented out because the same error as above occurred. When "pos_ary[n]" was used, the following error statement was output.
>>> 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
In line 105, when "pos[n]" was used, another error message was generated. This is the same as "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

