【3.1】分子指纹提取-RDKit

一、Topological Fingerprints

也叫RDKit topological fingerprint。该算法受Daylight fingerprint启发而产生,它会计算所有介于minPath和maxPath之间的分子路径(子图,subgraphs),对每个子图进行哈希运算,产生一个原始的bit ID。对bit ID取模(除数是fpSize),并在相应的位上进行设置。 对子图做哈希运算,其实就是对原子和键做哈希,它考虑了原子类型、芳香性、键的类型三种特征

对每个子图生成指纹的大致流程:

  1. 对子图计算一个哈希值
  2. 使用哈希值生成一个raw ID
  3. 对raw ID取模
  4. 如果nBitsPerHash大于1,根据raw ID再随机生成一个数,直到达到指定值
  5. 组成分子指纹相应的位。

使用rdkit来生成拓扑分子指纹

计算拓扑分子指纹:RDKFingerprint(mol, minPath,maxPath, fpSize, nBitsPerHash, useHs, tgtDensity, bitInfo, …)

mol:mol对象
minPath:默认1。生成子图所需的最少键的数量
maxPath:默认7。生成子图时最多键的数量
fpSize:生成指纹的长度,默认2048
nBitsPerHash:默认2。每个子图对应的位数。如果大于1,就将raw ID作为种子随机生成若干个数。
useHs:默认True,将显式氢考虑进指纹中。
tgtDensity:默认0。如果大于0,指纹长度会不断减半,直到大于等于设置的密度,或到达minSize的设置值。
bitInfo:用于接收指纹结果的字典。键为位数,值为相同指纹的列表(列表的每个元素为键的序号)。

示例:

>>> ms = [Chem.MolFromSmiles('CCOC'), Chem.MolFromSmiles('CCO'), Chem.MolFromSmiles('COC')]
>>> fps = [Chem.RDKFingerprint(x) for x in ms]
>>> fps
[<rdkit.DataStructs.cDataStructs.ExplicitBitVect at 0x7538300>,
 <rdkit.DataStructs.cDataStructs.ExplicitBitVect at 0x75383f0>,
 <rdkit.DataStructs.cDataStructs.ExplicitBitVect at 0x7538670>]

先简单地进行一下相似性比较

相似度比较:DataStructs.FingerprintSimilarity(fp1, fp2)

>>> DataStructs.FingerprintSimilarity(fps[0], fps[1])
0.6

通过传入空字典rdkinfo获取非空分子指纹信息 黄色表示带有芳香性质的原子

>>> mol = Chem.MolFromSmiles('c1ccccc1CC1CC1')
>>> rdkinfo = {}
>>> rdkfp = Chem.RDKFingerprint(mol, bitInfo=rdkinfo)
>>> Draw.DrawRDKitBit(mol, list(rdkinfo.keys())[0], rdkinfo)

二、MACCS

是一种基于SMARTS的,长度为167的分子指纹,每一位所代表的含义可以参考openbabel的介绍

>>> from rdkit.Chem import MACCSkeys
>>> fps = [MACCSkeys.GenMACCSKeys(x) for x in ms]
>>> DataStructs.FingerprintSimilarity(fps[0],fps[1])
0.5
>>> fps[0].GetNumBits()
167

三、Atom Pairs and Topological Torsions

这两种指纹算法的概念在30多年前提出,比较相似,指纹会包括原子序号、π电子数和相邻原子数三个维度的信息。此外还可以通过参数,加入手性的信息。两种指纹都可以用sparse form和explicit form形式来表示,并且可以查看指纹所代表的化学信息。

  • 计算atom pair指纹:GetAtomPairFingerprint(mol, minLength, maxLength, …)
  • 同GetAtomPairFingerprintAsIntVect()

这个方法生成的指纹非常庞大稀疏。

>>> from rdkit.Chem.AtomPairs import Pairs
>>> fps = [Pairs.GetAtomPairFingerprint(x) for x in ms]

可以通过该方法获取atom pairs算法产生的非空元素:GetNonzeroElements() 返回值是一个字典,键为指纹所在的位,值为出现的频数。

>>> fps[2].GetNonzeroElements()
{541730: 1, 1606689: 2}

也可以查看位所代表的指纹:Pairs.ExplainPairScore()

>>> Pairs.ExplainPairScore(1606689)
(('C', 1, 0), 1, ('O', 2, 0))

该结果表示这样一种子结构:有1个相邻原子和0个π电子的碳原子,通过一个键,与有2个相邻原子和0个π电子的氧原子相连。

也可以用一个定长向量来表示atom pair:GetAtomPairFingerprintAsBitVect() 注意:该方法不会记录子结构的频数,只用0和1表示是否存在。

>>> pairFps = [Pairs.GetAtomPairFingerprintAsBitVect(x) for x in ms]
>>> pairFps[0].GetNumBits()
8388608
>>> DataStructs.DiceSimilarity(pairFps[0],pairFps[1])
0.2222222222222222

生成Topological Torsion指纹:GetTopologicalTorsionFingerprint(mol, targetSize, …) 同GetTopologicalTorsionFingerprintAsIntVect()

mol:mol对象 targetSize:子图的长度

>>> from rdkit.Chem.AtomPairs import Torsions
>>> ttfp = Torsions.GetTopologicalTorsionFingerprintAsIntVect(ms[0])

获取非空元素:GetNonzeroElements() 查看位所代表的指纹:ExplainPairScore()

>>> ttfp.GetNonzeroElements()
{4320149536: 1}
>>> Torsions.ExplainPathScore(4320149536)
(('C', 1, 0), ('C', 2, 0), ('O', 2, 0), ('C', 1, 0))

四、Morgan Fingerprints (Circular Fingerprints)

摩根分子指纹,也成为圆形指纹,是采用摩根算法而产生。使用时,需要提供原子半径。这里只展示最基本的使用方法,更多关于指纹生成、提取与展示的操作可以参考这篇文章

以SparseBitVects方式生成摩根指纹:GetMorganFingerprint(mol, radius) radius:考虑半径

>>> mfp = [AllChem.GetMorganFingerprint(x, 2) for x in ms]
>>> mfp[0].GetLength()
4294967295

查看非空元素:GetNonzeroElements() 这里记录的指纹是包括频数的

>>> mfp[2].GetNonzeroElements()
{864674487: 1, 2154640335: 1, 2246728737: 2, 3975275337: 2}

以ExplicitBitVects方式生成摩根指纹:GetMorganFingerprintAsBitVect(mol, radius, nBits) radius:考虑半径 nBits:指纹长度

这种方法将不再记录频数

>>> mfp = [AllChem.GetMorganFingerprintAsBitVect(x, 2, nBits=10) for x in ms]
>>> print(mfp[0].GetNumBits())
10
>>> print(mfp[0].ToBitString())
0010100100
>>> print(DataStructs.DiceSimilarity(mfp[0], mfp[1]))
0.75

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn