第3章 分子文件格式转换概述:SDF、MOL2、PDB、PDBQT的差异及转换原则

做计算化学的人,手里最常打交道的就是这些分子文件。我自己折腾过的项目不下上百个,遇到过最头疼的事——明明是同一个分子,换了个格式读进去,原子对不上了,电荷跑偏了,键序也没了。嗯,说白了,格式之间那点“隐藏规则”,才是坑的地方。

这一章我先带你快速扫一遍SDF、MOL2、PDB、PDBQT四种格式长什么样,各自记什么、不记什么。然后再聊转换时的基本规则——怎么把数据搬过去还能保持物理意义不变。

格式差异:它们到底存了什么?

你想象一下,每个分子文件就是一张卡片。有些卡片画了键,有些只标了坐标;有些写了原子类型,有些留空。我列了一张对比表,核心差异一目了然。

特性SDFMOL2PDBPDBQT
原子坐标3D / 2D3D3D(Å)3D(Å)
键信息完整键表 + 键序完整键表 + 键类型无(可推算残基连接)无(使用AutoDock内置键搜索)
原子类型元素符号Sybyl原子类型元素符号 + 残基名AutoDock类型 + 部分电荷
电荷可选(字段内)每个原子带部分电荷无每个原子带Gasteiger电荷
可旋转键标记无无无有(ROT表)
官能团/残基无无残基名 + 链号无

我的经验:SDF 和 MOL2 是配体转换的“好上游”,因为键信息完整。PDB 更适合蛋白骨架,PQR 格式才带电荷,PDBQT 是 AutoDock 的“特供”,少了键表但多了可旋转键标记。

光看表还不够。我拿一个苯环举个例子,看看同一个分子在不同格式下怎么写。

SDF 格式:带键表的瑞士军刀

SDF(Structure Data File)其实是 mol 文件的“增强版”——核心是一个 mol 块,后面可以跟自定义数据字段。mol 块里面原子块和键块是分开写的。我个人习惯用SDF做配体存储,因为它能同时保留下坐标、键序、还有库里的额外信息(比如名字、SMILES)。

Molfile block example for benzene (C6H6)
  -OEChem-01302023003D

  6  6  0     0  0  0  0  0  0999 V2000
    1.3983    0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    0.6991    1.2103    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.6991    1.2103    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -1.3983    0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
   -0.6991   -1.2103    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    0.6991   -1.2103    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
  1  2  2  0  0  0  0
  2  3  1  0  0  0  0
  3  4  2  0  0  0  0
  4  5  1  0  0  0  0
  5  6  2  0  0  0  0
  6  1  1  0  0  0  0
M  END

注意那个键块里第三列的数字:2代表双键,1代表单键。这在后面转成PDBQT时,AutoDock需要根据键序推断哪些单键可旋转。

MOL2 格式:自带原子类型和部分电荷

MOL2 是 Sybyl 软件的老格式。它把原子、键、以及每个原子的类型写在一起。一个很大的好处是——它明确表达了原子杂化状态。举个例子,sp² 碳和 sp³ 碳在 MOL2 里是不同的类型(C.2 vs C.3)。

@<TRIPOS>MOLECULE
benzene
  6  6  1  0  0
SMALL
GASTEIGER

@<TRIPOS>ATOM
      1 C1        1.3983    0.0000    0.0000 C.2     1  BENZENE  0.0000
      2 C2        0.6991    1.2103    0.0000 C.2     1  BENZENE  0.0000
      3 C3       -0.6991    1.2103    0.0000 C.2     1  BENZENE  0.0000
      4 C4       -1.3983    0.0000    0.0000 C.2     1  BENZENE  0.0000
      5 C5       -0.6991   -1.2103    0.0000 C.2     1  BENZENE  0.0000
      6 C6        0.6991   -1.2103    0.0000 C.2     1  BENZENE  0.0000

@<TRIPOS>BOND
     1    1    2  ar
     2    2    3  ar
     3    3    4  ar
     4    4    5  ar
     5    5    6  ar
     6    6    1  ar

最后一列“0.0000”是部分电荷(这里用的是 Gasteiger 电荷)。你看,它的键类型用“ar”表示芳香键——这个信息在转换时很有用,因为 AutoDock 需要区分芳香碳和脂肪碳。

我曾经把一个MOL2文件的Gasteiger电荷直接复制到PDBQT,结果对接能量差了一大截。后来才发现MOL2里默认电荷单位是原子单位,PDBQT需要按e⁻(电子电荷)来写——其实是一样的,但精度差两位小数就会让对接结果乱跳。一定要用整数化后的电荷(乘1000取整)。

PDB 格式:蛋白世界的通用语言

PDB 当初是为蛋白质晶体结构设计的,所以它的世界观是“残基 + 原子名”。一个配体分子在PDB里通常写成HETATM记录。PDB格式最大的缺陷:它不记键,不记电荷,甚至氢原子都常常缺失。

HETATM    1  C1  LIG     1       1.398   0.000   0.000  1.00  0.00           C
HETATM    2  C2  LIG     1       0.699   1.210   0.000  1.00  0.00           C
HETATM    3  C3  LIG     1      -0.699   1.210   0.000  1.00  0.00           C
HETATM    4  C4  LIG     1      -1.398   0.000   0.000  1.00  0.00           C
HETATM    5  C5  LIG     1      -0.699  -1.210   0.000  1.00  0.00           C
HETATM    6  C6  LIG     1       0.699  -1.210   0.000  1.00  0.00           C
END

做对接的时候,很多工具拿PDB读配体——但缺失键信息,就得依赖原子间距离去“猜”键。有时距离阈值设错,苯环的六个碳会连成一条线。所以我的建议是:尽量别直接从PDB转PDBQT,除非你清楚知道编辑器已经补了键。

PDBQT 格式:AutoDock 的专属名片

PDBQT 全称 Protein Data Bank, Partial Charge (Q) & Atom Type (T)。它继承PDB的行格式,但加了两个新列:原子类型(比如C、A、HD、OA等)和部分电荷(整数化后写的,单位是千分之一电子电荷)。另外在文件末尾用ROTATABLE BONDS区块记录哪些单键可旋转。

HETATM    1  C1  LIG     1       1.398   0.000   0.000  0.000  0.00    0.0000    0.0000    0.0000 C   0
HETATM    2  C2  LIG     1       0.699   1.210   0.000  0.000  0.00    0.0000    0.0000    0.0000 C   0
HETATM    3  C3  LIG     1      -0.699   1.210   0.000  0.000  0.00    0.0000    0.0000    0.0000 C   0
HETATM    4  C4  LIG     1      -1.398   0.000   0.000  0.000  0.00    0.0000    0.0000    0.0000 C   0
HETATM    5  C5  LIG     1      -0.699  -1.210   0.000  0.000  0.00    0.0000    0.0000    0.0000 C   0
HETATM    6  C6  LIG     1       0.699  -1.210   0.000  0.000  0.00    0.0000    0.0000    0.0000 C   0
END
ROTATABLE BONDS
BRANCH   1   2
BRANCH   2   1
BRANCH   3   4
BRANCH   4   3
BRANCH   5   6
BRANCH   6   5
ENDROT

你仔细看——PDBQT里没有键表,但AutoDock在运行时收到文件后会做一套自己的键等价划分。所以PDBQT转换最关键的一步是:正确分配原子类型。比如一个sp²碳应该写成C(芳香碳),而不是A(脂肪碳)。我曾经因为把苯环碳标成了A,对接时程序把它当成可旋转的烷基链,自由度算错了一大堆。

转换原则:怎么搬才不翻车?

不管从哪种格式转到PDBQT,有几个原则你最好刻在脑子里。我把它们总结成五条。

  1. 原子类型映射:SDF/MOL2里的元素符号要映射到AutoDock的原子类型(C、A、N、O、S、H、HD、HA等)。芳香碳是A,脂肪碳是C,这部分我自己会写一个查表脚本。
  2. 电荷计算与整数化:PDBQT要求电荷写成千分之一电子电荷单位的整数。Gasteiger电荷是最常用的方法,但要注意MOL2自带的部分电荷可能已经是半经验值,不能直接照搬。
  3. 键信息重建:如果源文件没有键表(比如PDB),需要根据距离+元素类型+可能的手性推算。这步最容易出错。
  4. 可旋转键的确定:对于配体,主链上只含单键且非环的非末端键才可旋转。AutoDock的算法会把键分成ROT与ROT-Free,你需要确保ROTATABLE BONDS区域正确。
  5. 加氢处理:PDBQT里的配体一般要有氢原子。SDF/MOL2可能自带氢,也可能没有。别忘了加氢,否则对接时有些氢键位点会丢失。

避坑指南:我最开始做转换时,总以为把SDF读入Open Babel直接输出PDBQT就完事了。结果有次对接一个含手性中心的配体,发现镜像构象的能量反而更低——后来排查发现,Open Babel在加氢时默认加了极性H但没加非极性H,导致手性中心附近的立体化学信息丢失。从那以后我养成了一个习惯:先用保立体的工具(如RDKit)加氢,再转PDBQT。

知识结构图:四种格式的转换关系

下面这张SVG图帮你把四种格式之间的转换方向、关键步骤和注意点画在一个图里。本质上讲,转换是“信息增减”的过程——你从信息丰富的格式(SDF/MOL2)向信息精简的格式(PDBQT)走时,必须自己补上缺失的信息。

分子文件格式转换关系图 SDF 键表 + 坐标 + 字段 MOL2 原子类型 + 电荷 + 键类 PDB 坐标 + 残基名(无键) PDBQT 类型 + 电荷 + 可旋转键 类型映射 丢掉键表 保留电荷 加类型/电荷 转换关键操作 ① 加氢(RDKit优先) ② 分配原子类型 ③ 计算Gasteiger电荷 ④ 整数化电荷(×1000) ⑤ 推断可旋转键 ⑥ 生成ROTATABLE BONDS ⚠ 检查芳香碳 vs 脂肪碳 ⚠ 手性中心立体保留

转换路线图:实际项目中怎么走?

我按经验给一条最稳的流程。你拿到一个SDF配体文件,想做成PDBQT做分子对接——不走弯路。

  1. 输入检查:看看SDF里有没有氢原子。没有?先加氢(立体化学正确)。
  2. 读取键表:从mol块里提取所有键序。注意芳香键通常被写成4或5,要转换成AutoDock能识别的状态。
  3. 分配原子类型:写一个查表字典,比如sp²碳→A,sp³碳→C,羟基氧→OA,等等。这一步我一般用Open Babel的obabel命令,但需要后处理校验。
  4. 电荷计算:用Gasteiger电荷。推荐用RDKit的rdkit.Chem.AllChem.ComputeGasteigerCharges,结果乘以1000取整。保存到PDBQT的charge列。
  5. 确定可旋转键:遍历键表,排除环内键、双键、三键、末端的单键(比如甲基上的C-H键)。剩下的就是可旋转键。
  6. 生成PDBQT文件:按标准格式写ATOM/HETATM记录,然后在文件末尾写ROTATABLE BONDS表。

一个小窍门:如果你只是做快速批量转换,用meeko(一个专门配体准备的工具)自动生成PDBQT,它会处理电荷和可旋转键。但手动控制场景(比如特定原子类型修正),还是写脚本更可控。