RDkit:smiles编码、智能编码和摩根指纹(ECFP)简介
在介绍这三种编码之前,我们先来简单介绍一下rdkit中可以识别并相互转换的数据格式:.smi(即smiles编码的形式),.mol(即分子图的形式),.sdf(分子坐标的形式),……这几种是比较常用的,如果遇到一些不常见的,可以参考rdkit源包中的Chem模块。
SMILES编码
SMILES编码的全称是:Simplified Molecular-Input Line-Entry System
码如其名,其实smiles编码就是一种用文本字符串定义分子的常用模式。SMILES字符串以对化学家来说既简洁又直观的方式描述了分子的原子和键。
与其他分子表述方法相比smiles编码有两个优势:
1.唯一性:每个SMILES编码对应唯一一个化学结构,同时每个化学结构对应的SMILES编码也是唯一的,二者是一一对应的关系。
2.节省空间:SMILES的另一个重要特征是,与大多数其他表示结构的方法相比,它能节省存储空间。SMILES占用的空间甚至比二进制表减少50%至70%,此外,SMILES的压缩非常有效。通过Ziv-Lempel压缩,可将相同数据库存储内存减少到其原始大小的27%。
smiles编码的规则请参考下面这篇博文,在实际操作中,即使你不掌握编码规则也没有关系,只要会用rdkit就可以了。
在rdkit包的Chem模块中,在拥有分子smiles编码的前提下,可以通过smiles编码得到分子的一些理化性质,具体过程见下面代码展示:
import pandas as pd
import rdkit
from rdkit import Chem
from rdkit import rdBase, Chem
from rdkit.Chem import PandasTools, Descriptors, rdMolDescriptors, MolFromSmiles
from rdkit.Chem import QED,Lipinski
from moses.metrics import SA,mol_passes_filters
# 此表格仅一列,为分子的smiles编码,标题为0
df = pd.read_csv('smiles.csv')
# 解析:计算其logP,MW,HBA+HBD,TPSA,NRB
df['logP'] = df['0'].apply(lambda x: Descriptors.MolLogP(Chem.MolFromSmiles(x)))
df['TPSA'] = df['0'].apply(lambda x: Descriptors.TPSA(Chem.MolFromSmiles(x)))
df['MW'] = df['0'].apply(lambda x: Descriptors.MolWt(Chem.MolFromSmiles(x)))
df['HBA'] = df['0'].apply(lambda x: rdMolDescriptors.CalcNumLipinskiHBA(Chem.MolFromSmiles(x)))
df['HBD'] = df['0'].apply(lambda x: rdMolDescriptors.CalcNumLipinskiHBD(Chem.MolFromSmiles(x)))
# 计算QED
df['QED'] = df['0'].apply(lambda x:(QED.properties(Chem.MolFromSmiles(x))))
# 计算SA
df['SA'] = df['0'].apply(lambda x: SA(Chem.MolFromSmiles(x)))
SMART编码
SMART编码是前面描述的SMILES语言的扩展,可以用来创建查询。可以将SMART模式看作类似于用于搜索文本的正则表达式(换一种说法就是,smart编码相当于对smiles编码的一种模糊搜索)。
SMART编码一般用于下面几种情况:
搜索分子数据库以识别包含特定子结构的分子;
将一组分子排列在一个共同的子结构上,以提高视觉效果;
突出显示图中子结构
在计算过程中约束子结构
对于SMART编码的编码规则参照其官网,与smiles编码是一样的,即使你不掌握编码规则也没有关系,只要会用rdkit就可以了。
Daylight>SMARTS Exampleshttps://www.daylight.com/dayhtml_tutorials/languages/smarts/smarts_examples.html#ES_AM下面代码块展示一个Smart编码使用的小例子:
from rdkit import Chem
from rdkit.Chem import ChemicalFeatures
from rdkit import RDConfig
from rdkit.Chem import Draw
from rdkit.Chem import AllChem
from rdkit.Chem.Pharm2D.SigFactory import SigFactory
from rdkit.Chem.Pharm2D import Generate, Gobbi_Pharm2D
import os
import pandas as pd
# 已知一些分子的smiles编码,可通过rdkit处理得到其smart编码——下面分别将咪唑和胍基转换成smart格式
S1 = Chem.MolToSmarts(Chem.MolFromSmiles('C1NCNC1'))
S2 = Chem.MolToSmarts(Chem.MolFromSmiles('NC(=N)N'))
# 咪唑:[#6]1-[#7]-[#6]-[#7]-[#6]-1;胍基:[#7]-[#6](=[#7])-[#7]
# 读入数据
df = pd.read_csv("smiles_sorted.csv")
# smile编码形式,单列,列title为0
suppl_list = df[0].tolist()
suppl_end = [Chem.MolFromSmiles(x) for x in suppl_list]
# 筛选胍基及咪唑基的函数
def pharmacophore_smarts(m):
'''传入mol格式列表'''
# 定义smart
PosIonizable_Guanidine = '[#7]-[#6](=[#7])-[#7]'
PosIonizable_Imidazole = '[#6]1-[#7]-[#6]-[#7]-[#6]-1'
atomPharma = {}
PosIonizable_1 = m.HasSubstructMatch(Chem.MolFromSmarts(PosIonizable_Guanidine))
PosIonizable_2 = m.HasSubstructMatch(Chem.MolFromSmarts(PosIonizable_Imidazole))
return PosIonizable_1,PosIonizable_2
# 筛选胍基及咪唑基——得到结果的DataFrame表格
result = pd.DataFrame([pharmacophore_smarts(m) for m in suppl_end],columns=['PosIonizable_1','PosIonizable_2'])
# 去除不符合条件的数据
result_new = result.drop(result[result.PosIonizable_1 == False].index)
result_new = result.drop(result[result.PosIonizable_2 == False].index)
result_new.index
# 画出符合条件的分子结构
from rdkit.Chem import Draw
draw = [suppl_list[i] for i in result_new.index]
mols=[]
for m in draw:
mol = Chem.MolFromSmiles(m)
mols.append(mol)
img=Draw.MolsToGridImage(mols,molsPerRow=4,subImgSize=(300,300),legends=['' for x in mols],returnPNG=False)
img.save('demo.png')
摩根指纹(ECFP)
化学指纹是由1和0组成的向量,表示分子中特定的结构存在或不存在,摩根指纹又叫扩展——连接指纹是一类结合了几个由用特征的特征化表示。它们可将任意大小的分子转换成固定长度的向量。这很重要,这很重要,因为许多模型都要求输入具有完全相同的大小。ECFPs可以接受许多不同大小的分子,并由相同模型使用。ECFPs也很容易比较。利用ECFPs编码可以通过Tanimoto距离来计算分子相似性。
对摩根指纹的编码形式及原理感兴趣的,可以看下面这两篇文献(1.DOI:10.1021/ci9803381; 2.DOI:10.1021/ci100050t)
嘿嘿,我又来了,同样的话反复啰嗦,即使你不掌握编码规则也没有关系,只要会用rdkit就可以了。
下面一部分代码展示一个ECFP使用的小例子:
import pandas as pd
import rdkit
from rdkit.Chem import AllChem
from rdkit import Chem,DataStructs
import seaborn as sns
from scipy import stats
import matplotlib.pyplot as plt
data = pd.read_csv('moses_qed_props.csv')
# 读入数据为单列的smiles编码形式
data_1 = data.SMILES.tolist()
# 生成摩根指纹函数
def product_fps(data):
"""传入smiles编码文件列表"""
data = [x for x in data if x is not None]
data_mols = [Chem.MolFromSmiles(s) for s in data]
data_mols = [x for x in data_mols if x is not None]
data_fps = [AllChem.GetMorganFingerprintAsBitVect(x,3,2048) for x in data_mols]
return data_fps
# 计算分子相似度函数
def similar(data):
"""传入smiles编码文件列表"""
fps = product_fps(data)
similarity = []
for i in range(len(fps)):
sims = DataStructs.BulkTanimotoSimilarity(fps[i],fps[:i])
similarity.extend(sims)
return similarity
# 函数调用并打印
fps = product_fps(data_1)
print(f'fps:{fps[:20]}')
similarity = similar(data_1)
print(f'similarity:{similarity[:20]}')
(注:与smiles编码不同,ECFP不具有唯一性)
每周一篇rdkit相关小文章,总结不易,如果对您有帮助,希望能给个赞,多谢。