第4节:受体和配体文件的准备(PDBQT格式)

说实话,AutoDock Vina 跑对接的第一步,也是最容易翻车的一步,就是准备正确的输入文件。很多初学者兴冲冲地装好 Vina,直接把从 PDB 数据库下载的原始 `.pdb` 文件扔进去跑,结果不是报错就是结果离谱。

为什么会这样?因为原始 PDB 文件里有很多东西 Vina 不认识——结晶水、多余的配体、金属离子、不完整的侧链,还有最重要的:缺少氢原子和电荷。

Vina 要求输入文件必须是 PDBQT 格式。这个格式比普通 PDB 多了两列:Q(部分电荷)和 T(原子类型)。说白了,它告诉 Vina「哪个原子带多少电,属于什么类型,哪些键可以旋转」。

我个人习惯把这一步叫作「数据清洗+特征标注」——跟做机器学习一样,垃圾进,垃圾出。下面我带你一步步走完这个过程。

PDBQT 文件生成流程 原始 PDB 文件 ① 去除结晶水 / 冗余配体 / 金属离子 MGLTools / PyMOL / 手动编辑 ② 加氢 + 计算 Gasteiger 电荷 AutoDockTools → Edit → Add Hydrogen ③ 分配原子类型 + 可旋转键 AutoDockTools → Torsion Tree ④ 导出 PDBQT 文件 Ligand → Output → Save as PDBQT 检验文件 + 备份原始结构 为什么要改格式? • Vina 不识别 PDB 中的 标准残基名 • 缺少氢 → 无法判断 氢键供体/受体 • 没有电荷 → 静电打分无效 常见陷阱 • 配体芳香环错误分 配原子类型 • 蛋白质缺失侧链 导致静电计算偏差 • 可旋转键没设置

4.1 PDBQT 格式的结构

我先快速讲一下 PDBQT 长什么样。它和 PDB 很像,但每行末尾多了两列。

ATOM      1  N   THR A   1      -2.323   0.193  -1.597  0.00  0.00    -0.500 N
ATOM      2  CA  THR A   1      -1.080   0.134  -0.800  0.00  0.00     0.140 C
ATOM      3  C   THR A   1      -0.529   1.550  -0.598  0.00  0.00     0.620 C
ATOM      4  O   THR A   1      -1.202   2.529  -1.069  0.00  0.00    -0.500 OA
ATOM      5  CB  THR A   1      -1.202  -0.663   0.516  0.00  0.00     0.140 C

注意到倒数第二列了吗?那是 部分电荷(Partial Charge),最后一列是 原子类型(AutoDock Atom Type)。Vina 打分函数里的静电项靠这个 Q 值,疏水项和 π-π 堆积靠这个 T 值。

列位内容说明
1-6ATOM / HETATM记录类型,配体用 HETATM
7-11原子名称保持与原始 PDB 一致
12-16残基名 + 链蛋白质用标准三字母码
17-26残基编号整数序号
31-54X Y Z 坐标单位 Å
55-66Occupancy + Temp Factor通常填 0.00 0.00
67-76部分电荷Gasteiger 电荷,浮点数
77-78原子类型C, N, O, P, S, H, F, Cl, Br, I, A, OA, NA, SA, HD, MG, N3 等

关键点:配体的电荷总和必须为整数(或接近零)。如果电荷和是 0.45 这种,说明 Gasteiger 计算有问题,对接结果会凭空多出静电偏差。

4.2 获取受体和配体结构

这一步看似简单,其实坑不少。我总结了几类主流来源:

  • RCSB PDB 数据库(PDB ID):最权威,但文件里通常包含结晶水、缓冲剂分子、多构象。
  • AlphaFold / ESMFold 预测结构:没有配体共结晶结构时的选择。记得检查 plDDT 置信度,低置信度区域直接删掉。
  • 自己构建的配体(SMILES → 3D):用 RDKit 或 Open Babel 生成初始构象。我建议生成多个低能构象,不要只用最稳定那个——对接时 Vina 会采样扭转角,但好的初始构象能加速搜索。

举个例子,用 RDKit 从 SMILES 生成配体 3D 结构:

from rdkit import Chem
from rdkit.Chem import AllChem

mol = Chem.MolFromSmiles('CCO')  # 乙醇
mol = Chem.AddHs(mol)
AllChem.EmbedMolecule(mol, AllChem.ETKDG())
AllChem.MMFFOptimizeMolecule(mol)
print(f"原子数: {mol.GetNumAtoms()}")
Chem.MolToPDBFile(mol, 'ligand_ethanol.pdb')

避坑指南:我曾经从 PDB 下载了一个激酶结构,带着原配体直接准备受体文件。结果原配体里有个硫酸根离子被我当成水删掉了,电荷平衡直接崩了,对接打分全都偏正十几 kcal/mol。花了两天才排查出来。记住:受体文件必须不含任何配体、水、离子(除非是结构必需的金属离子)。

4.3 加氢与电荷计算

这是最核心的一步。原始 PDB 里的氢原子几乎全缺失(X 射线衍射看不到氢),而 Vina 打分函数却严重依赖氢键。没有氢,供体和受体都识别不出来。

我推荐用 AutoDockTools(ADT) 来做这个操作。原因有几点:

  • 加氢时会自动根据 pH 调整组氨酸质子化状态
  • 内置 Gasteiger-Marsili 电荷计算器
  • 能正确设置芳香环的原子类型(A 和 OA)

在 ADT 里的标准流程:

# 受体操作步骤
1. File → Read Molecule → 选择 .pdb 文件
2. Edit → Add Hydrogen → 选择 Add Only
   (如果蛋白质有金属离子,选 Add Including Hydrogens on Metals)
3. Edit → Gasteiger Charge → Compute
4. File → Save → Write PDBQT → 保存为 receptor.pdbqt

# 配体操作步骤
1. File → Read Molecule → 选择配体 .pdb
2. Edit → Add Hydrogen → Add
3. Edit → Gasteiger Charge → Compute
4. Ligand → Torsion Tree → Detect Root
   (自动检测可旋转键)
5. Ligand → Torsion Tree → Choose Torsions
   (手动调整:固定酰胺键、酯键等不要旋转)
6. Ligand → Output → Save as PDBQT → 保存为 ligand.pdbqt

4.4 原子类型分配规则

ADT 会自动分配原子类型,但有时会出问题。尤其是配体中含有杂环、卤素、硝基等基团时。我遇到过好几次 ADT 把芳香环上的氮原子误标为 N(非芳香氮),导致 π-π 堆积打分直接失效。

原子类型说明常见错误
C碳(非芳香)芳香碳误标为 C 而非 A
A芳香碳在苯环、吡啶环上必须用 A
OA芳香氧(如呋喃)酯基氧有时被误标为 OA
N氮(非芳香)胺基、酰胺 N
NA芳香氮(如吡啶 N)吡咯氮也可能被标为 N
HD氢键供体上的氢OH、NH 上的 H 必须为 HD
F / Cl / Br / I卤素ADT 有时漏标 F

你可以手动检查并修正 PDBQT 文件里的原子类型列。用文本编辑器打开配体 PDBQT,看一下芳香环上的碳是不是 A 而不是 C。如果不是,用 sed 或 Python 脚本批量替换:

# 把吡啶环上的 C 改为 A(但只改环上的,不要改取代基上的)
sed -i 's/^ATOM.\{12\}\(C2\|C3\|C4\|C5\|C6\).*$/& A/' ligand.pdbqt

我的习惯:写完 PDBQT 后,我会用 Python 读一遍,统计每种原子类型的数量,再和期望结构对比。如果 C 和 A 的数量不对,肯定有问题。写个几行脚本做自动化校验,能省掉很多手动查错的时间。

4.5 可旋转键的设置

Vina 在对接过程中会采样配体的扭转角。但并不是所有单键都应该旋转。

  • 应该旋转的:sp³-sp³ 单键、sp³-sp² 单键(除了特殊情况)
  • 不应该旋转的:酰胺键(保持平面,因为存在共振)、酯键(最好固定,否则打分函数会过度惩罚)、环内单键(环不能被拆开)

在 ADT 的 Torsion Tree 界面里,绿色表示可旋转,红色表示固定。默认设置通常是对的,但总有例外。

# 用 Open Babel 在命令行直接设置可旋转键
obabel ligand.pdb -O ligand.pdbqt --rotatable --gen3d

# 但这个方法会有遗漏,建议还是用 ADT 手动确认

我曾经犯过的错:有一次做糖类配体的对接,忘了把吡喃环上的端基异构键固定。Vina 硬是把环劈开了,得分看起来不错,但构象根本不对。从那以后,我每次都会检查环上的键是不是都被固定为红色。

4.6 批量处理与脚本化

如果你需要处理几百个配体,手动操作是不可能的。我用一套 Python + ADT 的脚本做批量准备。

核心思路是:用 ADT 的 Python API 调用 prepare_ligand4.py 和 prepare_receptor4.py。

# 批量准备配体
import os
import subprocess

pdb_directory = "./ligands_pdb/"
output_directory = "./ligands_pdbqt/"

for filename in os.listdir(pdb_directory):
    if filename.endswith(".pdb"):
        input_path = os.path.join(pdb_directory, filename)
        output_path = os.path.join(output_directory, filename.replace(".pdb", ".pdbqt"))
        cmd = f"prepare_ligand4.py -l {input_path} -o {output_path}"
        subprocess.run(cmd, shell=True)
        print(f"Done: {filename}")

如果你用 ADFR 套件(AutoDock-FR),还有更现代的 prepare_ligand 和 prepare_receptor 工具,支持多线程和自动修复。我强烈推荐它做批量。

4.7 文件检验清单

每次准备完文件,我都会过一遍这个清单:

检查项方法正常结果
PDBQT 格式无空行cat -A 查看没有 ^@ 或连续换行
原子类型全部合法grep -o ' [A-Z]\+$' | sort -u只含 AutoDock 标准类型
电荷和(配体)awk 求和倒数第二列整数(±0.01 以内)
可旋转键数量查看文件头部的 ROOT 后 BRANCH 数量一般在 0-20 之间
受体是否含有配体grep HETATM只能有必需的金属离子或辅因子
氢原子 HD 类型grep HD所有氢键供体 H 均为 HD

说实话,这个清单看着很琐碎,但你在批量处理 500 个配体时,任何一个环节出问题都会导致整个 VS 失效。我个人会把它写成一个 Python 脚本,自动跑一遍,不合格的文件直接标红。

老生常谈的提醒:永远保留原始 PDB 文件的备份。我习惯把原始文件放在 ./raw/ 目录,做好质量控制再进入 ./clean/。万一发现 PDBQT 准备有误,不需要重新下载,直接从备份重做就行。

4.8 一个小案例:用 Open Babel 替代 ADT

如果你没法用 ADT(比如在纯命令行环境),Open Babel 也可以生成 PDBQT,但不如 ADT 精细。

# 配体转换
obabel my_ligand.sdf -O my_ligand.pdbqt --gen3D --partialcharge gasteiger

# 受体转换
obabel receptor_protein.pdb -O receptor.pdbqt -xr

-xr 参数默认只加极氢(对 Vina 来说够用)。但 Open Babel 有一个缺点:它不认识 AutoDock 的全部原子类型(尤其是 A 和 OA 的区分),可能导致芳香性判断错误。

我的建议是:小数据集用 ADT,大数据集再用 Open Babel 批量,但一定要抽样手动检查。


文件准备这一步,我花了大量篇幅来讲。因为它直接决定了后面几十个对接跑下来,得到的是可重复的物理意义,还是无意义的数字游戏。你花 30 分钟把 PDBQT 弄清楚了,后面节省的可能是几天的时间。