pysmiles:一個用於讀寫SMILES表達式的python庫

技術背景

SMILES表達式是化學裡面常用的用於標定元素之間關係的字元串,旨在用最簡短的語句來完整的表達一個分子體系內所蘊含的基本資訊,比如元素、連接性以及連接屬性等。由於SMILES表達式的定義種類太多,需要完整介紹的可以閱讀這篇部落格或者是opensmiles的官方網站。這裡我們簡單介紹幾種常見的情況:

  1. 在SMILES表達式中,往往會去掉\(H\)元素,比如甲烷\(CH_4\)用SMILES表達式來表達的話就是\(C\)
  2. 雙鍵用\(=\)來表示,比如\(C(=O)=O\)表示一個二氧化碳;
  3. 三鍵用\(#\)來表示,用法與雙鍵一樣;
  4. 主幹線不加標記,分支加圓括弧,比如上面提到的二氧化碳,第一個\(O\)原子不在主分支上,因此加了括弧;
  5. 不成鍵的分子之間用.隔開,比如\(O.C(=O)=O\)表示一個水分子和一個二氧化碳分子;
  6. 成環的要打開來寫,並在開頭和結尾加上斷鍵標記,比如\(C1CCCCC1\)表示一個環己烷\(C_6H_{12}\),這裡的兩個1前所對應的碳是相互連接的。

諸如此類的複雜的化學表達式解析,最好是能夠有一個方便使用的工具來進行轉化,這裡介紹的是其中一款:pysmiles。

pysmiles的安裝

pysmiles是一個純粹用python寫的sdk,其中借用了networkx的框架來存儲元素之間的鍵連資訊。那麼我們可以直接使用pip來進行安裝和管理:

dechin@ubuntu2004:~/projects/gitlab/dechin/src/smile$ python3 -m pip install pysmiles
Collecting pysmiles
  Downloading pysmiles-1.0.1.tar.gz (34 kB)
Collecting pbr
  Using cached pbr-5.6.0-py2.py3-none-any.whl (111 kB)
Requirement already satisfied: networkx~=2.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from pysmiles) (2.5)
Requirement already satisfied: decorator>=4.3.0 in /home/dechin/anaconda3/lib/python3.8/site-packages (from networkx~=2.0->pysmiles) (4.4.2)
Building wheels for collected packages: pysmiles
  Building wheel for pysmiles (setup.py) ... done
  Created wheel for pysmiles: filename=pysmiles-1.0.1-py2.py3-none-any.whl size=22016 sha256=9c9bf6bf2f1667bfdb0d9a3c96f6d4499b7749b0ba4fc63ff45512c9dd1af8db
  Stored in directory: /home/dechin/.cache/pip/wheels/1b/ae/65/19c5062b483dbf3a22b8a42e32dfe1bdfc17f3d31b475e0d2f
Successfully built pysmiles
Installing collected packages: pbr, pysmiles
Successfully installed pbr-5.6.0 pysmiles-1.0.1

因為並沒有什麼特殊的依賴關係,所以安裝還是比較順利的。

pysmiles的使用

這裡我們通過一個簡單的案例來展示一下pysmiles的使用方法(其中關於networkx的使用,可以參考這一篇部落格):

from pysmiles import read_smiles
import networkx as nx
import matplotlib.pyplot as plt
    
smiles = 'N#CC#N' # 給定的SMILES表達式
mol = read_smiles(smiles) # 讀取到一個networkx的網路結構中
print(mol.nodes) # 列印節點資訊
print(mol.edges) # 列印邊資訊
print(nx.to_numpy_matrix(mol)) # 列印鄰接矩陣資訊

elements = nx.get_node_attributes(mol, name = "element")
nx.draw(mol, with_labels=True, labels=elements)
plt.savefig('pysmiles.png') # 保存圖層

上述是一個簡單的SMILES表達式讀取的程式,執行的結果如下所示:

dechin@ubuntu2004:~/projects/gitlab/dechin/src/smile$ python3 pysmiles_test.py 
[0, 1, 2, 3]
[(0, 1), (1, 2), (2, 3)]
[[0. 1. 0. 0.]
 [1. 0. 1. 0.]
 [0. 1. 0. 1.]
 [0. 0. 1. 0.]]

同時會在當前目錄下生成一個利用networkx畫出來的簡單圖片:

當然,這個結構有點過於的簡單,如果對於分子模型的展示稍微有點追求的話,可以參考這篇文章所介紹的vmd的使用方法。由於這裡我們只是傾向於使用pysmiles的閱讀功能,如果要使用pysmiles的寫入功能,可以參考如下官方案例,這裡不做過多的展開:

import networkx as nx
from pysmiles import write_smiles, fill_valence

mol = nx.Graph()
mol.add_edges_from([(0, 1), (1, 2), (1, 3), (3, 4), (1, 5), (3, 6)])
for idx, ele in enumerate('CCCCOCO'):
    mol.nodes[idx]['element'] = ele
mol.nodes[4]['charge'] = -1
mol.nodes[4]['hcount'] = 0
mol.edges[3, 6]['order'] = 2

print(write_smiles(mol))
# [O-]C(=O)C([C])([C])[C]
fill_valence(mol, respect_hcount=True)
print(write_smiles(mol))
# [O-]C(=O)C(C)(C)C

其實本質上也是通過構建一個networkx的數據結構,再通過這個數據結構去產生一個smiles的字元串。

總結概要

本文介紹了一款基於python語言的SMILES化學表達式的讀寫SDK,使用openSMILES表達式所定義的分子結構是非常精簡的,但是其中的規則又非常的多,因此使用一款友好的SMILES表達式能夠大大的縮減解析的成本。並且pysmiles結合了一款非常常用的python的拓撲網路結構表示SDK——networkx,使得對SMILES表達式的結果分析更加的人性化。

版權聲明

本文首發鏈接為://www.cnblogs.com/dechinphy/p/pysmiles.html
作者ID:DechinPhy
更多原著文章請參考://www.cnblogs.com/dechinphy/