python - 如何创建交互式脑形图?
问题描述
我正在networkx
和plotly
. 有没有办法创建一个类似于人脑外观的 3D 图形,networkx
然后将其可视化plotly
(因此它将是交互式的)?
这个想法是让节点在外面(或者只在更容易的情况下显示节点)并像上图一样为一组它们着色
解决方案
首先,这段代码大量借用了 Matteo Mancini,他在此处描述并在 MIT 许可下发布。
在原始代码中,没有使用 networkx,因此很明显您实际上并不需要 networkx 来实现您的目标。如果这不是严格的要求,我会考虑使用他的原始代码并对其进行修改以适应您的输入数据。
由于您将 networkx 列为要求,我只是重新编写了他的代码以获取Graph
具有某些节点属性的 networkx 对象,例如'color'
和'coord'
用于最终散点图中的那些标记特征。我只是选择了数据集中的前十个点来涂成红色,这就是它们没有被分组的原因。
完整的可复制粘贴代码如下。此处的屏幕截图显然不是交互式的,但您可以在 Google Colab 上尝试演示。
如果在 Linux/Mac 上的 Jupyter notebook 中下载文件:
!wget https://github.com/matteomancini/neurosnippets/raw/master/brainviz/interactive-network/lh.pial.obj
!wget https://github.com/matteomancini/neurosnippets/raw/master/brainviz/interactive-network/icbm_fiber_mat.txt
!wget https://github.com/matteomancini/neurosnippets/raw/master/brainviz/interactive-network/fs_region_centers_68_sort.txt
!wget https://github.com/matteomancini/neurosnippets/raw/master/brainviz/interactive-network/freesurfer_regions_68_sort_full.txt
- 否则:在此处下载所需文件。
代码:
import numpy as np
import plotly.graph_objects as go
import networkx as nx # New dependency
def obj_data_to_mesh3d(odata):
# odata is the string read from an obj file
vertices = []
faces = []
lines = odata.splitlines()
for line in lines:
slist = line.split()
if slist:
if slist[0] == 'v':
vertex = np.array(slist[1:], dtype=float)
vertices.append(vertex)
elif slist[0] == 'f':
face = []
for k in range(1, len(slist)):
face.append([int(s) for s in slist[k].replace('//','/').split('/')])
if len(face) > 3: # triangulate the n-polyonal face, n>3
faces.extend([[face[0][0]-1, face[k][0]-1, face[k+1][0]-1] for k in range(1, len(face)-1)])
else:
faces.append([face[j][0]-1 for j in range(len(face))])
else: pass
return np.array(vertices), np.array(faces)
with open("lh.pial.obj", "r") as f:
obj_data = f.read()
[vertices, faces] = obj_data_to_mesh3d(obj_data)
vert_x, vert_y, vert_z = vertices[:,:3].T
face_i, face_j, face_k = faces.T
cmat = np.loadtxt('icbm_fiber_mat.txt')
nodes = np.loadtxt('fs_region_centers_68_sort.txt')
labels=[]
with open("freesurfer_regions_68_sort_full.txt", "r") as f:
for line in f:
labels.append(line.strip('\n'))
# Instantiate Graph and add nodes (with their coordinates)
G = nx.Graph()
for idx, node in enumerate(nodes):
G.add_node(idx, coord=node)
# Add made-up colors for the nodes as node attribute
colors_data = {node: ('gray' if node > 10 else 'red') for node in G.nodes}
nx.set_node_attributes(G, colors_data, name="color")
# Add edges
[source, target] = np.nonzero(np.triu(cmat)>0.01)
edges = list(zip(source, target))
G.add_edges_from(edges)
# Get node coordinates from node attribute
nodes_x = [data['coord'][0] for node, data in G.nodes(data=True)]
nodes_y = [data['coord'][1] for node, data in G.nodes(data=True)]
nodes_z = [data['coord'][2] for node, data in G.nodes(data=True)]
edge_x = []
edge_y = []
edge_z = []
for s, t in edges:
edge_x += [nodes_x[s], nodes_x[t]]
edge_y += [nodes_y[s], nodes_y[t]]
edge_z += [nodes_z[s], nodes_z[t]]
# Get node colors from node attribute
node_colors = [data['color'] for node, data in G.nodes(data=True)]
fig = go.Figure()
# Changed color and opacity kwargs
fig.add_trace(go.Mesh3d(x=vert_x, y=vert_y, z=vert_z, i=face_i, j=face_j, k=face_k,
color='gray', opacity=0.1, name='', showscale=False, hoverinfo='none'))
fig.add_trace(go.Scatter3d(x=nodes_x, y=nodes_y, z=nodes_z, text=labels,
mode='markers', hoverinfo='text', name='Nodes',
marker=dict(
size=5, # Changed node size...
color=node_colors # ...and color
)
))
fig.add_trace(go.Scatter3d(x=edge_x, y=edge_y, z=edge_z,
mode='lines', hoverinfo='none', name='Edges',
opacity=0.3, # Added opacity kwarg
line=dict(color='pink') # Added line color
))
fig.update_layout(
scene=dict(
xaxis=dict(showticklabels=False, visible=False),
yaxis=dict(showticklabels=False, visible=False),
zaxis=dict(showticklabels=False, visible=False),
),
width=800, height=600
)
fig.show()
推荐阅读
- html - Codepen vs Bootstrap:CSS 行为不同
- azure-active-directory - 如何从控制台在 azure AD 应用程序中设置 oauth2AllowIdTokenImplicitFlow?
- html - 如何使用 ngFor 在表格中显示对象数组?
- zip - 如何使用 7zip 命令行工具将 CRC 属性添加到 Zip 文件?
- javascript - 由于某种原因,无法使用变量查找对象属性
- python - 更新 Keras 中的方法并导入
- corda - SystemUsers/Peer 没有权限='CREATE_ADDRESS'
- c# - 使用语句组合/合并 - c#
- python - 如何使用 panda_udf 对系列运行多个函数
- django - Azure 和 Django 错误:“您要查找的资源已被删除、名称已更改或暂时不可用”