Сохранение трехмерного графика, созданного в Networkx, в формат VTK для просмотра в Paraview - PullRequest
1 голос
/ 14 июля 2020

Я сгенерировал сеть 3D-графиков, используя следующий код, и Mayavi был использован для визуализации.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import networkx as nx
from mayavi import mlab


pos = [[0.1, 2, 0.3], [40, 0.5, -10],
       [0.1, -40, 0.3], [-49, 0.1, 2],
       [10.3, 0.3, 0.4], [-109, 0.3, 0.4]]
pos = pd.DataFrame(pos, columns=['x', 'y', 'z'])

ed_ls = [(x, y) for x, y in zip(range(0, 5), range(1, 6))]

G = nx.Graph()
G.add_edges_from(ed_ls)

nx.draw(G)
plt.show()


# plot 3D in mayavi
edge_size = 0.2
edge_color = (0.8, 0.8, 0.8)
bgcolor = (0, 0, 0)


mlab.figure(1, bgcolor=bgcolor)
mlab.clf()

for i, e in enumerate(G.edges()):
    # ----------------------------------------------------------------------------
    # the x,y, and z co-ordinates are here
    pts = mlab.points3d(pos['x'], pos['y'], pos['z'],
                        scale_mode='none',
                        scale_factor=1)
    # ----------------------------------------------------------------------------
    pts.mlab_source.dataset.lines = np.array(G.edges())
    tube = mlab.pipeline.tube(pts, tube_radius=edge_size)

    mlab.pipeline.surface(tube, color=edge_color)

mlab.show()

Я хотел бы попросить совета, как сохранить этот 3D-график в формате VTK / как для преобразования объекта графа Networkx в файл VTK для визуализации в Paraview.

РЕДАКТИРОВАТЬ: Я попытался адаптировать код, доступный здесь для входного графа Networkx, представленного выше. Однако я не могу получить результат. Я просто получаю пустое окно, а vtkpolyData не отображается в окне. Paraview будет действительно полезен.

1 Ответ

1 голос
/ 19 июля 2020

Если вы согласны с использованием vedo , который построен на основе vtk, это становится легко:

import networkx as nx

pos = [[0.1, 2, 0.3],    [40, 0.5, -10],
       [0.1, -40, 0.3],  [-49, 0.1, 2],
       [10.3, 0.3, 0.4], [-109, 0.3, 0.4]]

ed_ls = [(x, y) for x, y in zip(range(0, 5), range(1, 6))]

G = nx.Graph()
G.add_edges_from(ed_ls)
nxpos = nx.spring_layout(G)
nxpts = [nxpos[pt] for pt in sorted(nxpos)]
# nx.draw(G, with_labels=True, pos=nxpos)
# plt.show()

raw_lines = [(pos[x],pos[y]) for x, y in ed_ls]
nx_lines = []
for x, y in ed_ls:
    p1 = nxpos[x].tolist() + [0] # add z-coord
    p2 = nxpos[y].tolist() + [0]
    nx_lines.append([p1,p2])

from vedo import *
raw_pts = Points(pos, r=12)
raw_edg = Lines(raw_lines).lw(2)
show(raw_pts, raw_edg, raw_pts.labels('id'),
     at=0, N=2, axes=True, sharecam=False)

nx_pts = Points(nxpts, r=12)
nx_edg = Lines(nx_lines).lw(2)
show(nx_pts, nx_edg, nx_pts.labels('id'),
     at=1, interactive=True)

write(nx_edg, 'afile.vtk') # save the lines

enter image description here

The package also supports DirectedGraphs, so a second options is:

from vedo import *
from vedo.pyplot import DirectedGraph

# Layouts: [2d, fast2d, clustering2d, circular, circular3d, cone, force, tree]
g = DirectedGraph(layout='fast2d')
g.arrowScale =0.1
for i in range(6): g.addChild(i)
g.build()
show(g, axes=1)

write(g.unpack(0), 'afile.vtk')

РЕДАКТИРОВАТЬ: Следуя запросу,

Как включить цветовое отображение строк на основе скаляра с помощью cellColors():

# ... from the first example

from vedo import *
raw_pts = Points(pos, r=12)
raw_edg = Lines(raw_lines).lw(3)

nx_pts = Points(nxpts, r=12).c('red').alpha(0.5)
nx_edg = Lines(nx_lines).lw(2)

v1 = [sin(x)  for x in range(6)]
v2 = [sqrt(x) for x in range(6)]
vc = [x for x in range(nx_edg.NCells())]
labs1 = nx_pts.labels(v1, scale=.05).c('green').addPos(0.02,.04,0)
labs2 = nx_pts.labels(v2, scale=.05).c('red').addPos(0.02,-.04,0)
labsc = nx_edg.labels(vc, cells=True, scale=.04, precision=1, rotZ=-45)
labsc.c('black')

nx_edg.cellColors(vc, cmap='viridis').addScalarBar3D(c='k').addPos(.2,0,0)
# nx_edg.cellColors(vc, cmap='jet').addScalarBar() # this is a 2D scalarbar

show(nx_pts, nx_edg, labs1, labs2, labsc, axes=1)

enter image description here

How to hover points with the mouse to pop up a flag message with flag():

from vedo import *
raw_pts = Points(pos, r=12)
raw_edg = Lines(raw_lines).lw(3)

nx_pts = []
for p in nxpts:
    ap = Point(p, r=20).c('red').alpha(0.5)
    ap.flag('some text:\n'+'x='+precision(p[0],2)+'\ny='+precision(p[1],2))
    nx_pts.append(ap)

nx_edg = Lines(nx_lines).lw(3)
show(nx_pts, nx_edg, axes=1)

Как интерполировать цвет линии на значения узлов:

(NB: здесь clean() удаляет повторяющиеся точки, поэтому, пожалуйста, дважды проверьте возможные несоответствия с исходным массивом)

from vedo import *

nx_pts = Points(nxpts, r=12).c('grey').alpha(0.5)
nx_edg = Lines(nx_lines).lw(5)

v1 = [sin(x) for x in range(6)]
labs1 = nx_pts.labels(v1, scale=.05).c('green').addPos(0.02,.04,0)

nx_edg.clean().pointColors(v1, cmap='viridis').addScalarBar()

show(nx_pts, nx_edg, labs1, axes=1)

введите описание изображения здесь

...