N:::만지작 거리기
igraph와 plotly로 분자구조 그리기
joyHong
2022. 2. 15. 23:40
이번 글에서는 igraph와 plotly를 활용하여 분자구조를 2D와 3D로 그려보도록 한다.
데이터는 지난 블로그에서 생성한 아스피린 분자구조 그래프 데이터를 활용한다.
https://joyhong.tistory.com/150
igraph는 파이썬, R, C 등의 언어로 네트워크 분석을 할 수 있는 도구이다.
공식 홈페이지
3D로 분자구조를 그리기 위해서 plotly chart-studio의 scatter3d를 활용하도록 한다.
활용하는 라이브러리
!pip install igraph
!pip install chart-studio
!pip install kaleido
!pip install pycairo
라이브러리 임포트
import json
import igraph as ig
from chart_studio import plotly as py
import plotly.graph_objs as go
import numpy as np
2D로 아스피린 분자구조 그리기
지난 블로그에서 생성해 둔 JSON 형태의 데이터를 로딩해야 한다.
with open('graphData.json') as f:
data = json.load(f)
N=len(data['nodes'])
L=len(data['links'])
Edges=[(data['links'][k]['source'], data['links'][k]['target']) for k in range(L)]
노드와 엣지를 N과 Edges에 담아 두었다.
다음으로 엣지를 활용하여 그래프를 생성한다. 엣지에는 소스와 타켓이 들어있기 때문에 엣지를 읽어서 그래프를 생성할 수 있다.
G=ig.Graph(Edges, directed=False)
labels=[]
group=[]
for node in data['nodes']:
labels.append(node['name'])
group.append(node['group'])
노드의 레이블과 노드 그룹별 색상을 위해 각각 리스트에 담았다.
그래프는 igraph의 plot을 써서 그래프 데이터와 레이아웃을 정해주면 간단하게 그리게 된다.
layt=G.layout('kk', dim=2)
ig.plot(G, layout=layt, vertex_label=labels, bbox=(300,300))
여기서 적용한 레이아웃은 2차원의 Kamada-Kawai layout algorithm 이다.
3D로 그리기
먼저 2차원의 레이아웃을 3차원으로 생성하도록 한다.
layt=G.layout('kk', dim=3)
다음으로는 이 레이아웃을 통해 3차원으로 그리기 위한 좌표를 생성해야 한다.
Xn=[layt[k][0] for k in range(N)]
Yn=[layt[k][1] for k in range(N)]
Zn=[layt[k][2] for k in range(N)]
Xe=[]
Ye=[]
Ze=[]
for e in Edges:
Xe+=[[layt[e[0]][0],layt[e[1]][0], None]]
Ye+=[[layt[e[0]][1],layt[e[1]][1], None]]
Ze+=[[layt[e[0]][2],layt[e[1]][2], None]]
3D를 그릴 때 엣지를 그 종류에 따라 색상과 스타일을 적용해 보겠다.
traces = {}
line_style = {
"SINGLE" : {"color":"gray", "width":2, "dash":"solid"},
"AROMATIC" : {"color":"blue", "width":4, "dash":"longdashdot"},
"DOUBLE" : {"color":"red", "width":5, "dash":"longdash"},
}
for i in range(0, len(Edges)):
traces['trace_'+str(i)] = go.Scatter3d(x=Xe[i],
y=Ye[i],
z=Ze[i],
mode='lines+text',
hoverinfo='none'
)
trace_node=go.Scatter3d(x=Xn,
y=Yn,
z=Zn,
mode='markers+text',
name='actors',
marker=dict(symbol='circle',
size=6,
color=group,
colorscale='Viridis',
line=dict(color='rgb(50,50,50)', width=0.5)
),
text=labels,
textposition='bottom center',
hoverinfo='text'
)
axis=dict(showbackground=False,
showline=False,
zeroline=False,
showgrid=False,
showticklabels=False,
title=''
)
layout = go.Layout(
width=700,
height=700,
showlegend=False,
scene=dict(
xaxis=dict(axis),
yaxis=dict(axis),
zaxis=dict(axis),
),
margin=dict(
t=100
),
hovermode='closest',
)
Figure의 입력으로 위에서 생성한 trace들을 넣어주면 3D가 그려진다.
traces_link = list(traces.values())
traces_link.append(trace_node)
fig=go.Figure(data=traces_link, layout=layout)
fig
HTML 로 저장
생성한 이미지는 html로 저장이 가능하다.
import plotly.express as px
fig.write_html('plotly_graph.html')