缺失原子填补——给PDB模型“接骨”

做结构生物学的人,十有八九都碰过这样的糟心事:从PDB拿下来的结构,侧链原子缺一块,或者干脆整个残基只剩个主链。我入行那会儿,拿到一个激酶结构,活性位点的关键赖氨酸侧链全无,直接导致后续对接没法做。后来才明白,缺失原子不是结构本身的问题,而是电子密度图分辨率不够、或者精修时没建上模型。今天我们聊的,就是怎么把这些“断骨”接上。

缺失原子的常见类型与影响

不说虚的,先看看PDB里最常缺哪些原子。下表列了三种情况,你在实际项目中八成遇到过。

缺失类型典型表现对后续分析的影响
完全侧链缺失残基只保留CA、C、N、O不能做侧链相互作用分析,能量计算严重偏离
部分原子缺失侧链末端原子(如CD、NE、NZ)缺失氢键网络不完整,突变模拟缺少关键参考
主链原子缺失连续残基间缺CA或O破坏了蛋白质主链拓扑,直接报错

注意,主链缺失基本不可修复——建模风险太大,通常建议直接丢掉或重新解析。我们重点对付的是前两种。

两种主流填补方法概览

业界做填补,主流就两套:MODELER 和 AutoFill。简单说说区别。

  • MODELER 走的是“空间约束 + 立体化学最优”路线。我用它做同源建模时就发现,它对缺失段周围的主链构象敏感,但结果更自然,适合侧链空间关系复杂的场景。
  • AutoFill 依赖于旋转异构体库和片段匹配,说白了就是拿已知结构库里出现频率最高的位姿去填。速度比MODELER快一个量级,但遇到罕见构象时容易出错。

我个人习惯先看数据量:小规模补几个残基,AutoFill够用;大量缺失或对精度要求高的,MODELER更靠谱。

方法一:使用MODELER填补侧链

MODELER是Andrej Šali实验室开发的,原本做同源建模,但它的“填补缺失侧链”功能被单独剥离了出来。核心思路是:
保持主链不动 → 自动生成缺失侧链的初始坐标 → 用分子力学力场和立体化学约束迭代优化。

操作步骤

  1. 准备好起始PDB文件(缺失原子用ATOM行保留,HETATM可不管)。
  2. 写一个Python脚本,用MODELER的`optimize_missing_atoms`接口。
  3. 运行脚本,生成补全后的PDB。
  4. 检查输出中的残基Ramachandran图和clash。

脚本示例

from modeller import *
from modeller.scripts import optimize_missing_atoms

env = Environ()
env.io.hetatm = True          # 保留配体/水
env.io.water = True

# 读入已修复主链的PDB
mdl = Model(env, file='input.pdb')

# 自动填充缺失侧链
optimize_missing_atoms(mdl, output='filled.pdb',
                       optimize_sidechains=True,
                       max_iterations=100)

print("完成!新文件: filled.pdb")
提示:我建议把optimize_sidechains设为True,这样MODELER还会微调已有侧链的扭转角,减少空间冲突。如果担心主链偏移,可以把optimize_backbone锁死为False。

方法二:使用AutoFill(以PDBFixer为例)

AutoFill的代表工具之一是PDBFixer,它源自OpenMM生态,操作极其简洁。你可以用命令行完成,也能嵌入Python脚本。

命令行用法

pdbfixer input.pdb --output=fixed.pdb \
    --add-missing-atoms=heavy \
    --add-missing-hydrogens=no \
    --replace-nonstandard=yes

加`--add-missing-atoms=heavy`的意思是只补重原子(C、N、O、S),氢原子留着以后用PDB2PQR加。不加这个参数它也会补氢,但我个人习惯分开处理,避免pH不一致。

Python方式(更灵活)

from pdbfixer import PDBFixer
from openmm.app import PDBFile

fixer = PDBFixer('input.pdb')
fixer.findMissingResidues()
fixer.findNonstandardResidues()
fixer.replaceNonstandardResidues()
fixer.findMissingAtoms()

# 只填补重原子(默认补充完整侧链)
fixer.addMissingAtoms(seed=42)

# 输出
PDBFile.writeFile(fixer.topology, fixer.positions, open('fixed.pdb', 'w'))
print(f"补了 {len(fixer.missingAtoms)} 个残基的缺失原子")
注意:PDBFixer依赖于OpenMM,安装时需要conda install -c conda-forge pdbfixer openmm。我曾经在旧版conda环境下卡了半天,最后发现是OpenMM版本不匹配——建议新开一个干净环境。

两种方法对比

维度MODELERAutoFill (PDBFixer)
原理空间约束 + 立体化学优化旋转异构体库 + 片段匹配
速度较慢(迭代优化)快(几秒内补完一个结构域)
对主链的依赖高——主链偏移会导致出口中等——自动调整局部
典型应用场景同源建模、精细对接准备高通量筛选、批量预处理
输出稳定性高(但需要调参)中(罕见构象可能错)

实战建议与避坑

我的血泪教训:补完侧链一定要跑一次procheck或MolProbity检查。有次我用PDBFixer补了一个活性位点附近的组氨酸,结果咪唑环扭曲了30度,后续对接全废。后来手动挪了一下旋转异构体才搞定。

  • 先判断缺失范围:如果超过整个残基的40%缺失,建议用MODELER或直接放弃该残基。
  • 补完后必须做能量最小化:哪怕只是几百步steepest descent,也能消除明显的原子重叠。
  • 保留审计信息:我习惯在PDB的REMARK里记录补了哪些残基、用什么方法、参数版本。方便后来人(包括自己)追溯。
缺失原子填补流程图 探测缺失原子 选择方法 (根据精度/速度) AutoFill 片段库匹配 旋转异构体库 + 快速优化 MODELER 空间约束优化 迭代建模 + 立体化学约束 优化与验证 能量最小化 + 立体化学检测
补充一句:上面流程图里“优化与验证”这一步千万别省。我最初做过一批补完直接用的结构,结果对接时几个残基clash打分特别差——后来发现是侧链扭角没松弛。加个500步的L-BFGS最小化就能解决。

嗯,以上就是缺失原子填补的核心内容。两种方法各有侧重,不能说谁绝对好。你只要记住:先看缺失规模,再选工具,最后一定拿验证来兜底。我在实际项目中一般是MODELER打底、AutoFill批量跑初筛,互相校验,这么多年还没出过大问题。