N:::만지작 거리기

igraph와 plotly로 분자구조 그리기

joyHong 2022. 2. 15. 23:40

이번 글에서는 igraph와 plotly를 활용하여 분자구조를 2D와 3D로 그려보도록 한다.

데이터는 지난 블로그에서 생성한 아스피린 분자구조 그래프 데이터를 활용한다.

https://joyhong.tistory.com/150

 

Netwokx를 활용하여 분자구조 그리기

파이썬, 그래프 라이브러리를 활용하여 네트워크 그리기 기본 이해 NetworkX는 그래프와 네트워크를 연구하기위한 Python 라이브러리로서, BSD-new 라이센스에 따라 공개 된 무료 소프트웨어이다. 이

joyhong.tistory.com

 

igraph는 파이썬, R, C 등의 언어로 네트워크 분석을 할 수 있는 도구이다.

공식 홈페이지

https://igraph.org/

 

igraph – Network analysis software

igraph – The network analysis package igraph is a collection of network analysis tools with the emphasis on efficiency, portability and ease of use. igraph is open source and free. igraph can be programmed in R, Python, Mathematica and C/C++. igraph R p

igraph.org

3D로 분자구조를 그리기 위해서 plotly chart-studio의 scatter3d를 활용하도록 한다.

https://plotly.com

 

Plotly: The front end for ML and data science models

Dash apps go where traditional BI cannot: NLP, object detection, predictive analytics, and more. With 1M+ downloads/month, Dash is the new standard for AI & data science apps.

plotly.com

 

활용하는 라이브러리

!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

아스피린의 분자구조 3D 이미지

 

HTML 로 저장

 

생성한 이미지는 html로 저장이 가능하다.

import plotly.express as px

fig.write_html('plotly_graph.html')