RDKit 原子对指纹工具模块解析:AtomPairs.Utils 的原子编码位域与相似度度量
科学计算科研机器学习【免费下载链接】rdkitThe official sources for the RDKit library项目地址https://gitcode.com/gh_mirrors/rd/rdkit点击查看免费下载导读本文围绕 RDKit 官方文档页 rdkit.Chem.AtomPairs.Utils.rst 所记载的rdkit.Chem.AtomPairs.Utils模块展开系统讲解原子对Atom Pairs与拓扑扭转Topological Torsions指纹体系中最底层的两个能力把原子编码成紧凑整数的位域方案GetAtomCode/ExplainAtomCode与作用于排序 ID 序列的相似度度量BitsInCommon、DiceSimilarity、Dot、CosineSimilarity。读完本文你将掌握该模块每个函数的完整签名、参数语义、位运算原理以及它们如何被Pairs.py、Torsions.py、Sheridan.py调用形成可用的分子指纹并了解仓库中的回归测试如何保证结果稳定。一、模块定位AtomPairs 指纹家族的公共工具层RDKit 的 AtomPairs 目录下包含四个 Python 模块见 rdkit/Chem/AtomPairs模块职责Pairs.py原子对指纹Carhart 1985 论文实现Torsions.py拓扑扭转指纹Nilakantan 1987 论文实现Sheridan.py理化性质指纹 BP/BTKearsley 1996 论文实现Utils.py公共工具原子编码与相似度度量Utils.py本身不直接产出一份指纹它是上面三种指纹共同的积木指纹的每个非零项都建立在原子哈希值之上而两两比较指纹时又会复用其相似度函数。官方文档页Docs/Book/source/rdkit.Chem.AtomPairs.Utils.rst采用 Sphinxautomodule指令members、undoc-members、show-inheritance自动收集 Utils.py 中的 docstring 生成 API 参考因此本文将以该模块源码中的完整 docstring 与 doctest 为第一手素材展开。模块导出的核心 API 一览GetAtomCode(atom, branchSubtract0, includeChiralityFalse)—— 原子 → 整数编码ExplainAtomCode(code, branchSubtract0, includeChiralityFalse)—— 整数编码 → 可读元组BitsInCommon(v1, v2)—— 共同位 ID 计数DiceSimilarity(v1, v2, boundsNone)—— DICE 相似度Dot(v1, v2)—— 带重数加权的内积CosineSimilarity(v1, v2)—— 余弦相似度。二、GetAtomCode原子编码的位域布局GetAtomCode rdMolDescriptors.GetAtomPairAtomCodeUtils.GetAtomCode实际上是 C 函数GetAtomPairAtomCode的 Python 别名真实实现在 Code/GraphMol/Descriptors/Wrap/rdMolDescriptors.cpp 的封装与 Code/GraphMol/Fingerprints/AtomPairs.cpp 中。其把原子信息压缩进一个std::uint32_t位域布局在 Code/GraphMol/Fingerprints/FingerprintUtil.h 中定义const unsigned int numTypeBits 4; // 元素类型位宽 const unsigned int numPiBits 2; // π 电子数位宽 const unsigned int numBranchBits 3; // 邻接重数分支度位宽 const unsigned int numChiralBits 2; // 手性标记位宽 const unsigned int codeSize numTypeBits numPiBits numBranchBits; // 9 const unsigned int numPathBits 5; // 原子对距离位宽 const unsigned int maxPathLen (1 numPathBits) - 1; // 31类型4 bit查表 atomNumberTypes共 15 个可区分元素对应原子序数{5(B), 6(C), 7(N), 8(O), 9(F), 14(Si), 15(P), 16(S), 17(Cl), 33(As), 34(Se), 35(Br), 51(Sb), 52(Te), 53(I)}。Python 侧通过AtomPairsParameters.atomTypes暴露该表见 rdMolDescriptors.cpp。π 电子数2 bit取值范围 03超出按 3 截断maxNumPi。分支度3 bit即原子度数取值 07maxNumBranches。拓扑扭转指纹会利用branchSubtract参数调整它。手性2 bit可选0表示无手性、1表示 R、2表示 S。参数语义branchSubtract在编码前从邻接数中减去的常量用于拓扑扭转代码——路径两端原子减 1、中间原子减 2详见本文第五节。includeChirality是否把 R/S 标记编入哈希。注意即使分子无手性开启该开关也会改变指纹结果因为编码位数变了AtomPairs.h 的头部注释明确说明了这一点原子对指纹整体尺寸变化拓扑扭转则改变最大允许路径长度。使用示例来自 docstring from rdkit import Chem from rdkit.Chem.AtomPairs import Utils m Chem.MolFromSmiles(CCC(O)O) Utils.GetAtomCode(m.GetAtomWithIdx(0)) # 终端 C1 个重原子邻接1 个 π 电子 261三、ExplainAtomCode把编码还原为可读信息ExplainAtomCode(code, branchSubtract0, includeChiralityFalse)是GetAtomCode的逆操作按位域顺序依次用掩码取出分支数、π 电子数、类型索引必要时再取手性标记返回形如(元素符号, 分支度, π电子数)或(元素符号, 分支度, π电子数, 手性)的元组。实现见 Utils.pytypeMask (1 rdMolDescriptors.AtomPairsParameters.numTypeBits) - 1 branchMask (1 rdMolDescriptors.AtomPairsParameters.numBranchBits) - 1 piMask (1 rdMolDescriptors.AtomPairsParameters.numPiBits) - 1 chiMask (1 rdMolDescriptors.AtomPairsParameters.numChiralBits) - 1 nBranch int(code branchMask) # 低 3 位分支度 code code numBranchBits nPi int(code piMask) # 次 2 位π 电子数 code code numPiBits typeIdx int(code typeMask) # 再 4 位类型索引类型索引超出表长15时返回X手性用字典{0: , 1: R, 2: S}映射。一个值得注意的特性即使编码时带了手性只要includeChiralityFalse解码仍能得到正确的前三个字段——因为手性位位于类型位之后的高位不影响低 9 位。官方 docstring 演示 m Chem.MolFromSmiles(CCC(O)O) ExplainAtomCode(GetAtomCode(m.GetAtomWithIdx(0))) (C, 1, 1) # 原子 0C1 个邻接1 个 π 电子 ExplainAtomCode(GetAtomCode(m.GetAtomWithIdx(1))) (C, 2, 1) ExplainAtomCode(GetAtomCode(m.GetAtomWithIdx(2))) (C, 3, 1) ExplainAtomCode(GetAtomCode(m.GetAtomWithIdx(3))) (O, 1, 1) # 羰基 O ExplainAtomCode(GetAtomCode(m.GetAtomWithIdx(4))) (O, 1, 0) # 羟基 O无 π 电子手性示例CCHCl code GetAtomCode(m.GetAtomWithIdx(1), includeChiralityTrue) ExplainAtomCode(code, includeChiralityTrue) (C, 3, 0, R) ExplainAtomCode(code) # 不解手性也能正确解码 (C, 3, 0) m Chem.MolFromSmiles(CCHCl) # 反转构型 code GetAtomCode(m.GetAtomWithIdx(1), includeChiralityTrue) ExplainAtomCode(code, includeChiralityTrue) (C, 3, 0, S)非手性原子在第 4 个字段返回空串。testAtomPairTypesChiralitytestMolDescriptors.py也验证了未开启手性时两种对映体编码相同开启后互相不同。四、相似度度量作用于排序 ID 序列的四个函数这四个函数接受的输入是位 ID 序列例如SparseIntVect.GetNonzeroElements()排序后的键列表而不是SparseBitVect对象本身。共同约束输入向量必须已排序重复位 ID 会计多次。4.1 BitsInCommon —— 公共位计数 BitsInCommon( (1,2,3,4,10), (2,4,6) ) 2 BitsInCommon( (1,2,2,3,4), (2,2,4,5,6) ) # v1 有两个 2v2 也有两个 2各计一次 3实现为对两个有序序列的线性归并扫描Utils.py每个共同 ID 匹配一次计数一次。4.2 DiceSimilarity —— 论文推荐的 DICE 指标DiceSimilarity(v1, v2, boundsNone)实现 DICE 相似度。模块 docstring 明确指出这是 Atom Pairs 论文与 Topological Torsions 论文共同推荐的度量。公式为DICE 2 * BitsInCommon(v1, v2) / (len(v1) len(v2)) DiceSimilarity( (1,2,3), (1,2,3) ) 1.0 DiceSimilarity( (1,2,3), (5,6) ) 0.0 DiceSimilarity( (1,2,3,4), (1,3,5,7) ) 0.5 DiceSimilarity( (), () ) # 空向量边界情形 0.0重复位 ID 的处理规则是只有两边都重复才多计 DiceSimilarity( (1,1,3,4,5,6), (1,1) ) 0.5 DiceSimilarity( (1,1,3,4,5,6), (1,) ) 2./7 Truebounds参数用于过滤长度差异过大的比较当min(len(v1), len(v2)) / (len(v1) len(v2))小于bounds时分子强制为 0结果直接返回 0.0Utils.py。这在虚拟筛选场景中可快速剔除骨架差异过大的分子对 DiceSimilarity( (1,1,3,4), (1,1), bounds0.3 ) # 2/6≈0.333 ≥ 0.3正常计算 0.666... DiceSimilarity( (1,1,3,4,5,6), (1,1), bounds0.34 ) # 2/80.25 0.34直接 0 0.04.3 Dot —— 带重数的内积Dot(v1, v2)返回整数内积但并非简单按位点乘每个共同位 ID 按min(两边出现次数)计数再以min 值的平方累加Utils.py。这种计数平方的加权方式使重复出现的模式获得超线性权重 Dot( (1,2,3,4,10), (2,4,6) ) # 两个共同位各出现 1 次1²1² 2 Dot( (1,2,2,3,4), (2,2,4,5,6) ) # 2 出现 2 次与 2 次2²4 出现 1 次1² 5 Dot( (1,2,2,3,4), (2,4,5,6) ) # 2 一边 2 次一边 1 次min1 → 1² 2 Dot( (), (5,6) ) 04.4 CosineSimilarity —— LaSSI 论文推荐的余弦指标CosineSimilarity(v1, v2)返回浮点余弦相似度分子为Dot(v1, v2)分母为sqrt(Dot(v1,v1) * Dot(v2,v2))Utils.py。模块 docstring 注明这是 LaSSI 论文推荐的度量 print(%.3f % CosineSimilarity( (1,2,3,4,10), (2,4,6) )) 0.516 print(%.3f % CosineSimilarity( (1,2,2,3,4), (2,2,4,5,6) )) 0.714 print(%.3f % CosineSimilarity( (1,2,2,3,4), (1,2,2,3,4) )) 1.000 print(%.3f % CosineSimilarity( (1,2,2,3,4), (5,6,7) )) 0.000任一向量为空时denom 0返回 0.0。五、在原子对与拓扑扭转指纹中的调用链Utils的原子编码与解码函数被 Pairs.py 和 Torsions.py 直接复用形成完整的编码 → 组装 → 解码闭环。5.1 原子对Atom Pairs原子对指纹把两个原子的编码 拓扑距离压入一个整数。pyScorePairPairs.py演示了位组装规则accum int(dist) % _maxPathLen # 低 5 位距离最多 31 键 accum | min(code1, code2) numPathBits # 中段较小原子编码 accum | max(code1, code2) (codeSize numPathBits) # 高段较大原子编码把两个编码按大小排序再拼接保证原子 0-1 对与原子 1-0 对产生相同哈希。ExplainPairScore则按相反顺序用Utils.ExplainAtomCode还原为(原子A描述, 距离, 原子B描述) m Chem.MolFromSmiles(CCC) ExplainPairScore(pyScorePair(m.GetAtomWithIdx(0), m.GetAtomWithIdx(1), 1)) ((C, 1, 1), 1, (C, 2, 1))开启手性后codeSize增加numChiralBits位解码同样传includeChiralityTrue m Chem.MolFromSmiles(FCHCHCl) score pyScorePair(m.GetAtomWithIdx(1), m.GetAtomWithIdx(3), 1, includeChiralityTrue) ExplainPairScore(score, includeChiralityTrue) ((C, 3, 0, R), 1, (C, 3, 0, S))生产环境通常直接调用 C 封装rdMolDescriptors.GetAtomPairFingerprint含计数或GetHashedAtomPairFingerprint默认 2048 位。GetAtomPairFingerprintAsBitVectPairs.py则把计数指纹的非零键转成SparseBitVect其长度fpLen 1 (numPathBits 2*codeSize)即 2²³ 8,388,608 位不含手性。C 侧 AtomPairs.h 还暴露了更细的参数minLength/maxLength默认为 1 键与maxPathLen-130 键、fromAtoms/ignoreAtoms限定/排除某些原子参与、atomInvariants自定义原子不变量仅取每个值的前codeSize位、use2D/confId默认用 2D 拓扑距离也可改用 3D 构象距离。5.2 拓扑扭转Topological Torsions拓扑扭转指纹把一条路径上连续 4 个原子的编码按顺序拼成一个 64 位整数。pyScorePathTorsions.py的关键点在于branchSubtract的应用for i in range(size): if i 0 or i size - 1: sub 1 # 路径两端原子度数减 1 else: sub 2 # 中间原子度数减 2 codes[i] Utils.GetAtomCode(mol.GetAtomWithIdx(path[i]), sub)之后对编码向量做首尾比较的规范化从两端向中间比对若首元素更大则整体反转从而让路径 (0,1,2,3) 与 (3,2,1,0) 得到相同哈希。ExplainPathScore解码时把减去的sub加回去Torsions.py m Chem.MolFromSmiles(CCC(O)O) score pyScorePath(m, (0, 1, 2, 4), 4) ExplainPathScore(score, 4) ((C, 1, 1), (C, 2, 1), (C, 3, 1), (O, 1, 0))GetTopologicalTorsionFingerprintAsIdsTorsions.py把计数指纹展开为排序后的 ID 列表每个 ID 重复其计数次这个输出天然满足Utils相似度函数必须有序的前提可直接喂给BitsInCommon/DiceSimilarity m Chem.MolFromSmiles(C1CCCCN1) tt Torsions.GetTopologicalTorsionFingerprint(m) tt.GetNonzeroElements() {4437590049: 2, 8732557345: 2, 4445978657: 2} Torsions.GetTopologicalTorsionFingerprintAsIds(m) [4437590049, 4437590049, 4445978657, 4445978657, 8732557345, 8732557345]受 64 位整数上限约束targetSize * codeSize不得超过 64见 rdMolDescriptors.cpp不含手性时codeSize9最多 7 个原子开启手性后codeSize11最多 5 个原子。5.3 理化性质指纹Sheridan中的间接复用Sheridan.py 实现 Kearsley 的 BPAtom Pairs 变体/ BTTorsions 变体指纹先用 Data/SmartsLib/patty_rules.txt 把每个原子归类为CAT/ANI/POL/DON/ACC/HYD/OTH七类AssignPattyTypes再用rdFingerprintGenerator.GetAtomPairGenerator()/GetTopologicalTorsionGenerator()以类别码作为自定义原子不变量生成计数指纹。其依赖的codeSize位域常量与Utils同源体现了整个 AtomPairs 家族共用的编码骨架。六、测试与回归验证docstring 即测试Utils.py、Pairs.py、Torsions.py、Sheridan.py都内置了_runDoctests()入口模块被python直接执行时运行 doctest而 UnitTestDescriptors.py 通过doctest.DocTestSuite把四个模块的 docstring 全部纳入unittest测试套件tests.addTests(doctest.DocTestSuite(Pairs, optionflagsdoctest.ELLIPSIS)) tests.addTests(doctest.DocTestSuite(Sheridan, optionflagsdoctest.ELLIPSIS)) tests.addTests(doctest.DocTestSuite(Torsions, optionflagsdoctest.ELLIPSIS)) tests.addTests(doctest.DocTestSuite(Utils, optionflagsdoctest.ELLIPSIS))此外还有针对 1000 个分子的回归测试UnitTestDescriptors.py指纹结果与预生成的 gzip 打包 pickle 逐分子比对mols1000.aps.pkl.gz —— 原子对指纹期望值mols1000.tts.pkl.gz —— 拓扑扭转指纹期望值mols1000.pkl.gz —— 分子本体。testGithub334UnitTestDescriptors.py则单独回归了 π 电子计数规则如N#C两个原子各 2 个 π 电子、CC各 1 个因为 π 电子数是原子编码位域的关键组成部分直接影响指纹哈希。七、小结与使用建议理解编码位域GetAtomCode的 9 位核心编码4 位类型 2 位 π 3 位分支来自 FingerprintUtil.h解析分子指纹的调试场景用ExplainAtomCode还原注意类型表之外的索引返回X。相似度函数的使用前提BitsInCommon/DiceSimilarity/Dot/CosineSimilarity只接受有序ID 序列重复位按重数计DICE 是原子对与拓扑扭转论文的推荐指标余弦是 LaSSI 论文的推荐指标可按筛选场景选择。手性开关的代价includeChiralityTrue会改变指纹尺寸原子对或最大路径长度扭转即使分子本身无手性AtomPairs.h 对此有明确说明比较指纹时须保证两侧使用一致的生成参数。性能与召回平衡需要定长指纹时用哈希版本默认 2048 位、nBitsPerEntry4需要完整信息时用稀疏计数版本fromAtoms/ignoreAtoms可用于限定子结构参与比较。以测试为规范所有 docstring 示例均被 doctest 套件执行验证回归数据存放在 rdkit/Chem/AtomPairs/test_data修改相关实现时应保持这些测试通过。赞分享科学计算科研机器学习【免费下载链接】rdkitThe official sources for the RDKit library项目地址https://gitcode.com/gh_mirrors/rd/rdkit点击查看免费下载相关推荐如何给游戏更换 DLSS 版本DLSS Swapper 从零上手完整指南如何给游戏更换 DLSS 版本DLSS Swapper 从零上手完整指南 DLSS Swapper 是一款 Windows 上的图形增强库管理器专门负责帮你科学计算科研机器学习RDKit 中 Wildman-Crippen 原子型 LogP 与摩尔折射率MR计算指南rdkit.Chem.Crippen 模块深度解析RDKit 中 Wildman Crippen 原子型 LogP 与摩尔折射率MR计算指南rdkit.Chem.Crippen 模块深度解析 rdkit.科学计算科研机器学习CANN ops-math 余弦相似度算子 CosineSimilarity 深度解析原理、参数、约束与图模式调用CANN ops math 余弦相似度算子 CosineSimilarity 深度解析原理、参数、约束与图模式调用 本文围绕 CANN ops math 数学算子库人工智能CANN上一篇从内存参数异常到性能优化ZenTimings深度诊断实战指南下一篇3步解锁QQ音乐加密文件qmcdump免费转换工具完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考