第 2 章:受体准备 - 缺失原子与非标准残基处理

做分子对接,第一步就是准备受体。这一步要是没弄好,后面所有的对接结果都得打问号。

我自己早期翻过不少跟头——明明对接分数很高,结果一验证就发现配体卡在了蛋白的空腔里,原子间距根本不合理。排查到最后,发现是受体文件里缺了关键原子。嗯,那种感觉,白费了好几天功夫。

这一章咱们就专门聊聊:缺失原子和非标准残基这两个最容易出问题的地方。

核心口诀:原子不全不能跑,残基非标先建模。

2.1 缺失原子的常见情况

先说说缺失原子——这事太常见了。X光晶体结构或冷冻电镜解析出来的PDB文件,并不是完美的。有些原子的电子密度不清晰,结构学家就没法建模。

哪些原子最容易丢?

  • 侧链末端原子:比如赖氨酸的NZ原子、谷氨酸的OE原子。这些原子位于残基最外端,溶剂接触多,温度因子高。
  • 柔性侧链:精氨酸的NH2、谷氨酰胺的NE2等,在晶体里经常处于无序状态。
  • 氢原子:PDB通常不包含氢原子,除非是超高分辨率结构。对接前必须手动加氢。
  • 非极性侧链中段:像亮氨酸的CD1和CD2,有时候也会缺失。

我接手过一个项目,目标蛋白是某个激酶。PDB里一个关键的F169残基,侧链的Cβ和Cγ都显示为“未定义”。没补全之前,对接就是妥妥的负分。补全之后,姿势完全变了。

2.2 如何检测缺失原子

最简单的方法——用文本编辑器打开PDB文件,看看ATOM记录行里是不是有奇怪的占位符。

典型异常标志:

常见占位符 含义 处理方式
-999 坐标未确定 必须补全或删除该残基
0.000 坐标缺失或置零 需要重建原子坐标
ATOM 序列号 重复 原子编号冲突 重新编号并检查次序
HETATM 与 ATOM 混用 非标准残基标记错误 修正残基类型标记

我习惯用脚本批量跑一下。下面这个check_missing_atoms.py是我自己一直在用的,能快速扫描PDB里缺了哪些主链和侧链原子。

import sys
from Bio.PDB import PDBParser

def check_missing( pdb_file ):
    parser = PDBParser(QUIET=True)
    structure = parser.get_structure("prot", pdb_file)
    for model in structure:
        for chain in model:
            for residue in chain:
                std_atoms = {"N", "CA", "C", "O"}
                if residue.get_resname() in standard_amino_acids:
                    missing = std_atoms - { atom.get_id() for atom in residue }
                    if missing:
                        print(f"Chain {chain.id} Res {residue.get_resname()} {residue.id[1]}: missing {missing}")

if __name__ == "__main__":
    check_missing(sys.argv[1])

小技巧:有些可视化工具也能高亮缺失原子,比如PyMOL里set ignore_pdb_header_warnings, 1之后,用show sticks配合select missing可以快速定位。

2.3 补全缺失原子的常用方法

检测出来缺失以后,该怎么补?我推荐下面这几种方式,按适用场景分好优先级。

  1. 使用同源建模工具(Modeller / SWISS-MODEL)
    • 适合缺失片段较长(比如3个残基以上)的情况
    • 能根据同源模板,重建侧链和主链的合理构象
    • 缺点是耗时长,需要手动校验
  2. 用PDB Fixer类工具自动补全
    • 比如OpenMM的pdbfixer,可以一键补全缺失侧链
    • 底层逻辑是用Rotamer库来填充缺失原子
    • 适合单残基或小侧链缺失
  3. 手动编辑PDB文件,使用PyMOL的fill missing atoms命令
    • 快速,适合少量缺失
    • 但无法处理主链断裂或大段缺失

一个常见的补全命令示例(PyMOL):

fetch 1abc
fill missing atoms
save 1abc_filled.pdb

注意:补全原子后,务必检查二面角是否有立体化学冲突。我曾在补全一个色氨酸侧链时,没注意χ1角违反了拉氏图,结果对接一直无法收敛。折腾了两天才发现问题。

2.4 非标准残基的处理

非标准残基,指的是不在20种标准氨基酸列表里的残基。比如磷酸化的丝氨酸(SEP)、乙酰化的赖氨酸(ALY)、甲基化的精氨酸等。

这类残基在PDB里被标记为HETATM,而不是ATOM。对接软件默认把HETATM当作小分子配体处理,但事实上它们依然是受体的一部分——这就导致了很多对接失败。

我经历过的真实案例——一个磷酸化位点附近的对接。配体本来应该和SEP侧链的磷酸基团形成盐桥,但AutoDock把SEP当成了小分子配体拿出来单独处理。对接结果完全不对。后来我手动把SEP改成标准残基,再补上磷酸基的原子参数,结果才正常。

2.5 非标准残基的标准化流程

拿到一个非标准残基,我一般走这三步:

  1. 查看PDB报告——看这个残基有没有完整的原子坐标,有没有对应的化学修饰说明。
  2. 检查是否为天然修饰——比如磷酸(TPO)、甲基(MLY)、乙酰(ALY)等常见修饰,可以在对接工具里手动添加。
  3. 手动重建为可对接形式——给该残基分配标准原子命名,导出为MOL2或PDB格式,提供正确的键序和电荷。

下面是一个简单的函数,用来把磷酸化丝氨酸(SEP)还原为标准丝氨酸+磷酸基团,并输出成两段独立的分子对象:

def separate_phosphoserine(het_residue):
    # het_residue是Bio.PDB中的Residue对象
    std_ser = create_standard_residue("SER", het_residue.id[1])
    for atom in het_residue:
        if atom.get_name() in ['N', 'CA', 'C', 'O', 'CB', 'OG']:
            std_ser.add(atom.copy())
    # 剩余P、OP1、OP2、OP3归入磷酸基团
    phospho_group = Residue((' ', 1, ' '), 'PO4', '')
    for atom in het_residue:
        if atom.get_name() not in ['N', 'CA', 'C', 'O', 'CB', 'OG']:
            phospho_group.add(atom.copy())
    return std_ser, phospho_group

2.6 受体准备中的避坑清单

咱们来总结一下,实操中容易踩的坑。我用列表写清楚,你对照着检查一遍。

  • 缺失原子补全前,别忘了加氢——很多工具补全原子时不自动加氢,你得单独加一遍。
  • 主链断裂的不能直接补——如果缺失超过3个连续残基,建议还是用同源建模重新建模。直接硬补侧链,主链构象不连续。
  • 非标准残基不能全当配体处理——特别是磷酸化、甲基化这种共价修饰,它们依然是受体官能团的延伸。
  • PDB里的HETATM不都是小分子——比如血红蛋白里的血红素、酶里的金属离子,这些也是受体结构的一部分。
  • 补全后必须做能量最小化——哪怕只是补了一个原子,周围侧链的张力也可能很大。我建议做一轮500步最陡梯度下降。

我的一个习惯:每次补全都跑一遍ProCheck拉氏图检查,看看新加原子的二面角是否合理。比对着结构看感觉要准得多。

2.7 本章知识脉络

下面这张流程图,把受体准备中缺失原子和非标准残基的处理全过程串起来了。你可以先看一眼整体,再回头对照细节。

受体准备 — 缺失原子与非标准残基处理流程 获取原始PDB文件 检查缺失原子(主链+侧链) 缺失? 是 自动补全 / 同源建模 否 跳过原子补全 加氢原子(质子化状态) 非标? 是 分离修饰基团 + 重建 否 保留为ATOM记录 输出完整受体文件 能量最小化(500步) 注意 磷酸化、甲基化等 修饰要手动重建

说白了,受体准备这部分,最大的敌人就是“你以为文件没问题”。很多新手直接网上扒个PDB就开始对接,结果后面到处报错。花10分钟跑一遍缺失原子检测,补全非标残基,再做一轮最小化——对接成功率能翻倍。

最后强调一点:做完上面所有步骤,别忘了加氢。我曾经被一个pH=7.4环境下的组氨酸质子化状态坑过好多次——错过一个氢键,结果整个对接打分差了两个数量级。该用reduce还是用propka,看你的喜好,但这一步省略不得。