第4章:药物分子数据预处理概述:常见格式与清洗目标

做药物分子数据预处理,第一关永远是格式。SDF、SMILES、PDB——这三个家伙几乎占据了所有分子数据交换的场景。我记得刚入行时,接手一个虚拟筛选项目,上游给了几百个SDF文件,下游对接的模型死活只能读SMILES字符串。当时花了两天写格式转换脚本,结果发现字段对不齐、原子计数少了、立体化学信息丢失……从那以后,我再也不敢轻视格式预处理这一步了。

这章我们就聊透彻:这三种格式到底长什么样?它们各自擅长什么?最常踩的坑在哪?以及,我们最终要洗出什么样的数据。

1. SDF:结构数据文件

SDF(Structure Data File)可以说是化学信息学最通用的格式之一了。它来自MDL公司的CTfile规范,一个文件可以存一个或多个分子。结构片段(原子坐标、键连接)和数据字段(分子量、LogP、CAS号等)打包在一起。

我个人习惯在处理公共数据库(比如ChEMBL、PubChem)时优先看SDF,因为它是“结构+属性”的完整快照。你想想看,一个SDF文件长这样:

O1
  -MDL-0931160300

  9  9  0  0  0  0  0  0  0  0999 V2000
    1.2345    0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.3456    1.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    3.4567    0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    0.1234   -0.7000    0.0000 O   0  0  0  0  0  0  0  0  0  0  0  0
  1  2  1  0
  2  3  1  0
  3  1  1  0
  1  4  1  0
  3  4  1  0
M  END
> 
CHEMBL12345

> 
180.16

$$$$

每个分子以$$$$结束,atom block和bond block的数据列含义固定。这里有个坑:

小心字段缺失。 我曾经从某个公司数据库导出SDF,很多分子缺了$$$$分隔符或属性字段名不规范。结果Snakemake管道读入后直接报错,排查了一整天才发现是最后一条记录没闭合。所以写SDF解析器时,一定要检查记录数目和属性块完整性。

SDF的主要用途:

  • 存储小分子的完整2D/3D构象
  • 携带任意数目的用户自定义字段
  • 作为数据库导出/导入的标准格式

2. SMILES:一行搞定分子结构

SMILES(Simplified Molecular Input Line Entry System)是另一种极端——用一行ASCII字符串表示整个分子。它的核心是深度优先遍历连接图,再用分支和环标记。

举个例子,阿司匹林的SMILES是 CC(=O)Oc1ccccc1C(=O)O。你看,原子、双键、环编号、括号里的支链都在一行里。好处是极其轻量,适合网络传输、数据库主键、模型输入。坏处呢?

我在项目中遇到过很多“非标准SMILES”。比如:

  • 不规范环编号(不同工具对环的表示顺序不一样)
  • 缺少氢原子(隐式氢 vs 显式氢混用)
  • 立体化学信息模糊(@和@@符号位置搞反)

所以预处理时,我建议统一规范化工具,比如用Open Babel或RDKit的MolFromSmiles再MolToSmiles,这样能保证输出规范的Canonical SMILES。下面是一段Python演示:

from rdkit import Chem

smiles = "c1ccccc1C(=O)O"   # 不规范:苯环用低编号,但可接受
mol = Chem.MolFromSmiles(smiles)
canon = Chem.MolToSmiles(mol)   # 输出 O=C(O)c1ccccc1
print(canon)
记住: 在Snakemake管道中,我常用一个rule专门做SMILES标准化。输入可能是CSV里的糙字符串,输出统一格式的SMILES文件,为后续特征计算铺平道路。

3. PDB:蛋白质的坐标语言

PDB(Protein Data Bank)格式是生物大分子的标准。一个PDB文件记录每个原子的x、y、z坐标、残基名、链标识、温度因子等。小分子配体通常也会被放在HETATM记录区。

但处理PDB时最让人头疼的是数据不一致性:

  • 同一个蛋白可能有多个变体,原子编号不相同
  • 缺失残基、侧链断开
  • 溶剂分子、配体、离子混在一起
  • 分辨率低,导致坐标精度不足

我曾经处理一个对接项目,下游的AutoDock工具要求配体PDB文件中不能有氢原子,而受体需要极氢。结果上游给的文件里全混杂了,装进Snakemake后死活跑不过。后来我专门写了一个rule,用reduce工具加氢,再用obabel删掉非必要原子。

PDB文件中一个典型片段:

ATOM     22  CG  ASP A   3      -2.316   1.695   2.140  1.00  0.00           C  
ATOM     23  OD1 ASP A   3      -1.318   1.348   2.849  1.00  0.00           O  
ATOM     24  OD2 ASP A   3      -3.511   1.390   2.252  1.00  0.00           O  
HETATM   25  C1  LIG L   1       3.424  -0.877   0.556  1.00  0.00           C  
关键点: 在药物数据预处理中,PDB格式主要用于蛋白质受体预处理和配体-受体复合物准备。清洗目标通常是:删除水分子、保留配体、补齐缺失侧链、加氢、分配原子类型。

格式对比一览

属性 SDF SMILES PDB
表现方式 块结构 + 坐标 + 字段 一行字符串 固定宽度文本 + 坐标
适用范围 小分子(多记录) 小分子(单行) 生物大分子、配体复合物
立体化学 支持(parity字段) 支持(@/@@) 不直接,需残基命名推断
数据冗余 较大(含坐标+字段) 极小 较大(含晶胞等元信息)
主要清洗问题 字段缺失、分隔符错误、坐标异常 非标准环表示、隐式氢歧义、立体化学颠倒 原子编号不一致、缺失原子、水分子干扰、链定位
工具推荐 Open Babel, RDKit, obabel RDKit, Open Babel PyMOL, Reduce, Open Babel

清洗目标:我们要达到什么效果?

说来说去,预处理无非四个核心目标:

  1. 标准化 – 把所有输入格式统一成一种内部表示(比如SDF或Canonical SMILES),去掉没必要的信息(比如3D坐标转2D或统一原子类型)。
  2. 去重 – 同一个分子可能在不同数据库里出现了多次,SMILES表示可能不一样。我习惯先用InChI或Canonical SMILES去重,再根据结构相似性合并。
  3. 过滤异常 – 那些原子数<2的、分子量超千的、含有非标准元素的……统统该筛掉。记得有一次管道跑到一半,打印出来一个“分子”只有两个氢原子,加氢后变成H2,完全没意义。还好snakemake的日志提醒了我。
  4. 补齐缺失信息 – 比如从SMILES到3D坐标、加氢、分配原子类型。这些操作往往依赖RDKit或Open Babel,且应当做成可复用的rule。
避坑指南: 我曾经在清洗时没对SMILES做原子计数过滤,结果下游计算LogP的脚本报除零错误。事后我加了一个过滤rule,在SMILES生成后立刻检查原子个数,小于3的剔除并写入日志。这个小动作省了我无数排查时间。

下面是整个预处理的逻辑流程,我经常在纸上画出来再写Snakemake规则:

分子数据预处理流程 原始SDF 原始SMILES 原始PDB 其他格式 格式识别 & 解析 清洗:去重 / 过滤异常 / 加氢 / 标准化 (原子数检查、SMILES规范化、PDB补残基) 标准处理后的数据 提示 1. 先用小规模测试集摸清格式缺陷 2. 统一输出为Canonical SDF 3. 日志记录每个原始文件清洗统计

说白了,预处理就是“把脏数据擦干净、格式统一、规则明确”的过程。你想想看,如果输入是一团乱麻,后面再牛的模型也白搭。Snakemake的优势就在于你可以把上面的流程拆成一个个rule,每次只处理一个步骤,中间产物的文件通过通配符传递,可追踪、可复用。