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就可以了。

SMILES:一种简化的分子语言_xk6891的博客-CSDN博客_smile结构一.什么是SMILES SMILES,全称是Simplified Molecular Input Line Entry System,是一种用于输入和表示分子反应的线性符号,是一种ASCII编码,下面看一些例子: SMILES包含的信息可能与一些扩展的源数据表相同,SMILES更适用的主要原因是它是一种语言结构,而不是计算机数据结构。 SMILES是一种真正的语言,虽然只有简单的词汇(原子和键符号)和少数语法规则。 SMILES结构表示可以反过来用作其他语…https://blog.csdn.net/xk6891/article/details/116380262?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-3-116380262-blog-124738689.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-3-116380262-blog-124738689.pc_relevant_paycolumn_v3&utm_relevant_index=6(注:smiles编码是可以表示手性异构的)

在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相关小文章,总结不易,如果对您有帮助,希望能给个赞,多谢。

物联沃分享整理
物联沃-IOTWORD物联网 » RDkit:smiles编码、智能编码和摩根指纹(ECFP)简介

发表评论