You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部分SMILES调用Chem.RDKFingerprint报C++签名不匹配问题排查

配体匹配中的RDKit计算异常问题分析

问题背景

尝试匹配UniProt与PDB条目中的同一配体:多数配体(如FAD)三字母编码一致,但部分存在差异,例如血红蛋白1a9w链A在PDB中为“HEM”,对应UniProt条目(P69905)为“heme b”,其ChEBI ID为CHEBI:60344。

从ChEBI官网下载完整SDF文件后,找到3个相关血红素配体。以CHEBI:60344为参考计算Tanimoto系数时,部分配体运行正常,但CHEBI:26355触发Python无法捕获的C++异常;调整ChEBI ID顺序后代码直接报错无法得到系数。

环境:conda安装的rdkit、bioservices与Python3.9,运行于旧版Mac Pro(High Sierra系统,无法升级)。

执行代码

from rdkit import Chem, DataStructs
from bioservices import ChEBI
heme = ChEBI()
heme_chebi_id = "CHEBI:60344"
heme_smiles = heme.getCompleteEntity(heme_chebi_id).smiles
target = Chem.MolFromSmiles(heme_smiles)
fp2 = Chem.RDKFingerprint(target)
for chebi_id in ["CHEBI:17627", "CHEBI:26355"]:
    ch = ChEBI()
    smiley = ch.getCompleteEntity(chebi_id).smiles
    print("reference:", heme_chebi_id)
    print("target:   ", chebi_id)
    print("reference:", heme_smiles)
    print("target:   ", smiley)
    ref = Chem.MolFromSmiles(smiley)
    fp1 = Chem.RDKFingerprint(ref)
    Tan = DataStructs.TanimotoSimilarity(fp1, fp2)
    print(Tan)
    print("-" * 64)
exit()

输出结果

reference: CHEBI:60344
target:    CHEBI:17627
reference: CC1=C(CCC([O-])=O)C2=[N+]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N+]5[Fe--]3(n14)n1c(=C6)c(C)c(CCC([O-])=O)c1=C2

target:    CC1=C(CCC(O)=O)C2=[N+]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N+]5[Fe--]3(n14)n1c(=C6)c(C)c(CCC(O)=O)c1=C2
Tanimoto coefficient: 1.0

reference: CHEBI:60344
target:    CHEBI:26355
reference: CC1=C(CCC([O-])=O)C2=[N+]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N+]5[Fe--]3(n14)n1c(=C6)c(C)c(CCC([O-])=O)c1=C2
target:    CC1=C(CCC(O)=O)C2=[N]3C1=Cc1c(C)c(C=C)c4C=C5C(C)=C(C=C)C6=[N]5[Fe]3(n14)n1c(=C6)c(C)c(CCC(O)=O)c1=C2

[12:36:26] Explicit valence for atom # 9 N, 4, is greater than permitted
Traceback (most recent call last):
File "/Volumes/Users/harry/icl/phyre2-ligand/./tanimoto_test.py", line 20, in <module>
fp1 = Chem.RDKFingerprint(ref)
Boost.Python.ArgumentError: Python argument types in
rdkit.Chem.rdmolops.RDKFingerprint(NoneType)
did not match C++ signature:
RDKFingerprint(RDKit::ROMol mol, unsigned int minPath=1, unsigned int maxPath=7, unsigned int fpSize=2048, unsigned int nBitsPerHash=2, bool useHs=True, double tgtDensity=0.0, unsigned int minSize=128, bool branchedPaths=True, bool useBondOrder=True, boost::python::api::object atomInvariants=0, boost::python::api::object fromAtoms=0, boost::python::api::object atomBits=None, boost::python::api::object bitInfo=None)

问题原因分析

  1. ChEBI的SMILES字符串错误:CHEBI:26355返回的SMILES中,N原子的价态标注不符合化学规则(错误提示显示#9号N原子显式价为4,超出允许范围),导致RDKit无法将其解析为有效的分子对象(ref为None)。
  2. RDKit代码实现错误:代码中未检查Chem.MolFromSmiles()的返回值,当解析失败返回None时,直接将其传入RDKFingerprint(),触发C++层的参数类型不匹配异常。
  3. RDKit本身/bioservices模块无问题:RDKit的错误提示是解析无效SMILES的正常反馈;bioservices正确获取了ChEBI数据库返回的SMILES内容,不存在模块功能异常。

修复方案

1. 增加错误处理逻辑

在解析SMILES后检查分子对象是否有效,避免传入None到指纹计算函数:

from rdkit import Chem, DataStructs
from bioservices import ChEBI

# 只初始化一次ChEBI实例,避免重复创建
hebi_client = ChEBI()
heme_chebi_id = "CHEBI:60344"
heme_smiles = hebi_client.getCompleteEntity(heme_chebi_id).smiles
target = Chem.MolFromSmiles(heme_smiles)
if not target:
    print(f"Failed to parse reference SMILES for {heme_chebi_id}")
    exit()
fp2 = Chem.RDKFingerprint(target)

for chebi_id in ["CHEBI:17627", "CHEBI:26355"]:
    smiley = hebi_client.getCompleteEntity(chebi_id).smiles
    print("reference:", heme_chebi_id)
    print("target:   ", chebi_id)
    print("reference:", heme_smiles)
    print("target:   ", smiley)
    
    ref = Chem.MolFromSmiles(smiley)
    if not ref:
        print(f"Failed to parse SMILES for {chebi_id}, skipping...")
        print("-" * 64)
        continue
    
    fp1 = Chem.RDKFingerprint(ref)
    tanimoto = DataStructs.TanimotoSimilarity(fp1, fp2)
    print(f"Tanimoto coefficient: {tanimoto}")
    print("-" * 64)

2. 使用ChEBI的SDF文件获取结构

由于SMILES可能存在价态或立体信息丢失,建议直接从下载的SDF文件中读取分子结构,而非通过API获取SMILES:

from rdkit import Chem, DataStructs

# 读取ChEBI SDF文件
suppl = Chem.SDMolSupplier("chebi_lite_3star.sdf")
# 构建ChEBI ID到分子的映射
chebi_mol_map = {}
for mol in suppl:
    if mol is None:
        continue
    chebi_id = mol.GetProp("ChEBI ID")
    chebi_mol_map[chebi_id] = mol

# 获取参考分子
ref_mol = chebi_mol_map.get("CHEBI:60344")
if not ref_mol:
    print("Reference molecule not found in SDF")
    exit()
ref_fp = Chem.RDKFingerprint(ref_mol)

# 计算目标配体的Tanimoto系数
for chebi_id in ["CHEBI:17627", "CHEBI:26355"]:
    target_mol = chebi_mol_map.get(chebi_id)
    if not target_mol:
        print(f"Molecule {chebi_id} not found in SDF")
        continue
    target_fp = Chem.RDKFingerprint(target_mol)
    tanimoto = DataStructs.TanimotoSimilarity(ref_fp, target_fp)
    print(f"{heme_chebi_id} vs {chebi_id}: Tanimoto = {tanimoto}")

内容的提问来源于stack exchange,提问作者Ubuntu-on-Mac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 07:45:36