ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

RDKit VLib 虚拟库指南:用 SDSupplyNode 从 SDF 文件批量供应分子

RDKit VLib 虚拟库指南:用 SDSupplyNode 从 SDF 文件批量供应分子
  • 科学计算
  • 科研
  • 机器学习

【免费下载链接】rdkit

The official sources for the RDKit library

项目地址:https://gitcode.com/gh_mirrors/rd/rdkit
点击查看免费下载

本篇技术指南围绕 RDKit VLib(Virtual Library,虚拟库)框架中的SDSupplyNode展开,讲解如何将 SDF 格式的化合物文件接入虚拟库处理管线、以迭代器方式逐分子读取并支持可重复遍历。读完本文,你将掌握SDSupplyNode的构造、迭代、重置等完整用法,理解其与底层Chem.SDMolSupplier的协作关系,并能将其与过滤、去重、输出等节点自由组合,搭建可复用的高通量分子处理流水线。

一、VLib 框架与 Supply 节点定位

rdkit.VLib是 RDKit 中以"节点(Node)"为基本单元构建分子处理管线的模块,其包结构在 Docs/Book/source/rdkit.VLib.rst 中定义:核心子模块包括Node、Supply、Filter、Output、Transform,以及NodeLib子包中一系列开箱即用的具体节点。

  • VLibNode(rdkit/VLib/Node.py)是全部节点的基类,定义了迭代接口(__iter__/next/reset)与库图操作(AddParent、AddChild、GetParents、GetChildren、Destroy)。
  • SupplyNode(rdkit/VLib/Supply.py)是"供应者"节点的基类,其核心假设是没有父节点——它是一整条处理链的最上游,负责对外部数据源(内存列表、文件、数据库)产出分子对象。
  • SDSupplyNode正是SupplyNode的 SDF 文件特化实现,位于 rdkit/VLib/NodeLib/SDSupply.py。

从源码结构看,整个NodeLib包(rdkit/VLib/NodeLib/init.py)对外暴露了SmartsMolFilter、SDSupply、SmartsRemover、SmilesDupeFilter、SmilesOutput等模块,SDSupplyNode在其中扮演"数据入口"的角色。

二、SDSupplyNode 类的核心实现

2.1 构造参数

SDSupplyNode的构造函数定义如下:

def __init__(self, fileName, **kwargs): SupplyNode.__init__(self, **kwargs) self._fileName = fileName self._supplier = Chem.SDMolSupplier(self._fileName)

它只接收一个必填参数:

参数类型说明
fileNamestrSDF(Structure-Data File)文件的路径,用于构造底层的Chem.SDMolSupplier
**kwargs-透传给SupplyNode/VLibNode的额外关键字参数

2.2 迭代协议:next 与 reset

SDSupplyNode完整实现了 Python 迭代器协议:

def reset(self): SupplyNode.reset(self) self._supplier.reset() def next(self): return next(self._supplier) SDSupplyNode.__next__ = SDSupplyNode.next
  • next():每次调用从底层Chem.SDMolSupplier取下一个Mol对象;数据耗尽时抛出StopIteration,从而天然兼容for循环与列表推导。
  • reset():先调用父类SupplyNode.reset()将位置指针归零,再调用底层 supplier 的reset(),使文件流回到开头,实现可重复遍历。
  • 文件末尾的SDSupplyNode.__next__ = SDSupplyNode.next将旧的next()方法绑定到新式迭代协议上,保证next(suppl)与suppl.__next__()两种调用方式均可用。

三、底层机制:Chem.SDMolSupplier

SDSupplyNode本身不做 SDF 解析,而是委托给 RDKit 化学模块的Chem.SDMolSupplier(源码位置见 rdkit/Chem/init.py 的导入及 rdkit/Chem/UnitTestSuppliers.py 的测试验证)。这一设计的好处是:

  • 惰性读取:supplier 按需从磁盘解析分子,而非一次性把整个文件载入内存,适合大文件批量处理;
  • 属性继承:SDF 中的结构数据字段(如<NSC>、<CAS_RN>)会自动写入分子的属性字典,通过GetProp()读取;
  • 健壮的重复遍历:reset()后可以再次从头迭代,已被 rdkit/Chem/UnitTestSuppliers.py 的单元测试覆盖(断言reset()后首分子名称仍为'48',读完 10 个分子后再next会抛StopIteration)。

仓库还保留了已被弃用的FastSDMolSupplier(rdkit/Chem/FastSDMolSupplier.py),它只是Chem.SDMolSupplier的子类占位,官方建议直接使用后者。

四、实战用法:读取 SDF 并验证属性

SDSupplyNode自带可运行的 doctest 示例,其测试数据文件为 rdkit/VLib/NodeLib/test_data/NCI_aids.10.sdf(内含 10 个 NCI AIDS 筛选集分子,每个分子带有NSC、CAS_RN、NCI_AIDS_Antiviral_Screen_IC50等属性字段)。

import os from rdkit import RDConfig from rdkit.VLib.NodeLib.SDSupply import SDSupplyNode fileN = os.path.join(RDConfig.RDCodeDir, 'VLib', 'NodeLib', 'test_data', 'NCI_aids.10.sdf') suppl = SDSupplyNode(fileN) # 遍历全部分子 ms = [x for x in suppl] len(ms) # 10 ms[0].GetProp("_Name") # '48' ms[1].GetProp("_Name") # '78' # 重置后重新从头遍历 suppl.reset() suppl.next().GetProp("_Name") # '48' suppl.next().GetProp("_Name") # '78'

运行要点:

  1. RDConfig.RDCodeDir指向 RDKit 安装目录的代码根,用于拼接仓库自带测试数据路径;
  2. _Name属性由 SDF 文件第一个字段(分子标题行)自动填充,对应 NCI_aids.10.sdf 中的48、78等标题值;
  3. 除_Name外,还可以通过GetProp("NSC")、GetProp("CAS_RN")读取结构数据字段,与 rdkit/Chem/UnitTestSuppliers.py 中的底层 supplier 行为一致。

五、管线组合:将 SDSupplyNode 接入处理链

SDSupplyNode的价值在于作为处理链的起点。仓库自带的 rdkit/VLib/NodeLib/demo.py 展示了一条完整的组合管线(其中用内存SupplyNode替代了 SDF 输入,注释部分保留了真实用法):

from rdkit.VLib.NodeLib.SDSupply import SDSupplyNode fName = os.path.join(RDConfig.RDCodeDir, 'VLib', 'NodeLib', 'test_data', 'NCI_aids.10.sdf') supplier = SDSupplyNode(fName)

在此基础上可以继续挂接下游节点,例如:

# 1) 用 SMARTS 过滤掉含金属/镧系元素的分子 smaFilter = SmartsMolFilter.SmartsFilter(patterns=[metals], counts=[1]) smaFilter.SetNegate(1) smaFilter.AddParent(supplier) # 2) 用 SMARTS 移除盐离子片段 remover = SmartsRemover.SmartsRemover(patterns=salts) remover.AddParent(smaFilter) # 3) 按原子数过滤 atsFilter = Filter.FilterNode(func=lambda x: x.GetNumAtoms() > 1) atsFilter.AddParent(remover) # 4) 按规范 SMILES 去重 dupeFilter = SmilesDupeFilter.DupeFilter() dupeFilter.AddParent(atsFilter) # 5) 输出 SMILES 文本 output = SmilesOutput.OutputNode(dest=io, delim=', ', idField='Name') output.AddParent(dupeFilter)

各节点的协作机制:

  • AddParent建立数据流方向:下游节点调用next()时,会通过GetParents()向上游取数(见 rdkit/VLib/Node.py);
  • DupeFilter(rdkit/VLib/NodeLib/SmilesDupeFilter.py)用Chem.MolToSmiles的规范 SMILES 集合去重,其类文档中的示例正是以SDSupplyNode作为输入源;
  • OutputNode(rdkit/VLib/NodeLib/SmilesOutput.py)支持delim、idField参数,可输出ID, SMILES, 附加字段格式的文本。

注意:SupplyNode的AddParent会主动抛出ValueError('SupplyNodes do not have parents')(见 rdkit/VLib/Supply.py),因此SDSupplyNode只能作为链路首节点,任何试图为它添加父节点的操作都会失败——这是框架刻意保证的数据流单向性。

六、同族供应节点对比

NodeLib中还提供了另外两个基于SupplyNode的供应者,可对比选择:

节点数据源关键参数实现文件
SDSupplyNodeSDF 文件fileNamerdkit/VLib/NodeLib/SDSupply.py
SmilesSupplyNode文本文件(SMILES 行)fileName、delim、smilesColumn、nameColumn、titleLinerdkit/VLib/NodeLib/SmilesSupply.py
DbMolSupplyNode数据库结果集dbResultsrdkit/VLib/NodeLib/DbMolSupply.py

其中SmilesSupplyNode默认delim="\t"、smilesColumn=0、nameColumn=1、titleLine=False,其 doctest 使用 rdkit/VLib/NodeLib/test_data/pgp_20.txt 验证了列号与标题行配置(参见 rdkit/VLib/NodeLib/SmilesSupply.py)。三者的next()/reset()接口完全一致,可以在管线上互换使用。

七、测试与验证方式

SDSupplyNode的可信度由两层测试保证:

  1. doctest:类文档中的示例被 rdkit/VLib/NodeLib/UnitTestNodeLib.py 通过doctest.DocTestSuite(SDSupply, ...)收集执行;模块自身也保留了_runDoctests()入口(rdkit/VLib/NodeLib/SDSupply.py),可直接运行python SDSupply.py验证;
  2. 单元测试:rdkit/Chem/UnitTestSuppliers.py 覆盖了底层Chem.SDMolSupplier的迭代、重置、属性读取与StopIteration行为,而 rdkit/VLib/UnitTestVLib.py 验证了SupplyNode的迭代器与父节点约束。

八、小结

SDSupplyNode是 RDKit VLib 框架中最直接的 SDF 数据接入方案:它复用Chem.SDMolSupplier完成惰性解析,通过next()/reset()提供标准的可重复迭代语义,并以"无父节点"的供应者身份占据处理链首端。将其与SmartsMolFilter、SmartsRemover、SmilesDupeFilter、SmilesOutput等NodeLib节点通过AddParent串联,即可快速构建从 SDF 文件到结构化结果的完整虚拟库处理管线。

  • 科学计算
  • 科研
  • 机器学习

【免费下载链接】rdkit

The official sources for the RDKit library

项目地址:https://gitcode.com/gh_mirrors/rd/rdkit
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进