340

用 PDBFixer 修复蛋白结构:Docking 前处理流程

PDBFixer 修复蛋白结构是对接与模拟前的必经步骤。这篇给出完整修复脚本、每步的判断依据与修复后的检查清单。

直接拿原始 PDB 去做对接或模拟,是最常见也最容易被忽视的错误来源。晶体结构几乎总是不完整的:缺失侧链原子、缺失整段 loop、没有氢原子、含有结晶助剂。这一步不做好,后面所有计算都建立在错误的结构上。

安装

mamba install -c conda-forge pdbfixer openmm
pdbfixer --help          # 也有命令行与图形界面

标准修复流程(带诊断输出)

from pdbfixer import PDBFixer
from openmm.app import PDBFile

def fix_structure(pdb_input, pdb_output, ph=7.4,
                  keep_water=False, keep_hetero=None, verbose=True):
    fixer = PDBFixer(filename=pdb_input)

    # 1) 缺失残基(整段 loop)
    fixer.findMissingResidues()
    if verbose and fixer.missingResidues:
        print("缺失残基片段:")
        for (chain_idx, res_idx), residues in fixer.missingResidues.items():
            print(f"  链 {chain_idx} 位置 {res_idx}: {len(residues)} 个残基")

    # 关键判断:末端缺失通常可不补,位于结合位点附近的必须补
    # 若要跳过末端缺失:
    chains = list(fixer.topology.chains())
    keys_to_remove = []
    for key in fixer.missingResidues:
        chain = chains[key[0]]
        if key[1] == 0 or key[1] == len(list(chain.residues())):
            keys_to_remove.append(key)          # 末端
    for k in keys_to_remove:
        del fixer.missingResidues[k]

    # 2) 非标准残基(如硒代甲硫氨酸 MSE → MET)
    fixer.findNonstandardResidues()
    if verbose and fixer.nonstandardResidues:
        print("非标准残基:", fixer.nonstandardResidues)
    fixer.replaceNonstandardResidues()

    # 3) 杂原子处理 —— 这一步需要人工判断!
    fixer.removeHeterogens(keepWater=keep_water)

    # 4) 补缺失重原子(侧链)
    fixer.findMissingAtoms()
    if verbose and fixer.missingAtoms:
        print(f"缺失重原子的残基数: {len(fixer.missingAtoms)}")
    fixer.addMissingAtoms()

    # 5) 按 pH 加氢
    fixer.addMissingHydrogens(ph)

    PDBFile.writeFile(fixer.topology, fixer.positions,
                      open(pdb_output, "w"), keepIds=True)
    return fixer

fixer = fix_structure("1m17.pdb", "receptor_fixed.pdb", ph=7.4)

每一步的判断依据

步骤 判断
缺失残基 末端缺失可不补;结合位点附近的缺失 loop 必须处理,否则口袋形状是错的
杂原子 结晶助剂(甘油、DMSO、PEG、硫酸根)该删;催化金属、辅因子必须留
水分子 结合位点的保守水常参与桥接,是否保留需专门决定
加氢 pH 默认 7.4;组氨酸质子化态影响最大,关键位点建议人工核对
非标准残基 MSE→MET 通常安全;翻译后修饰要评估是否与功能相关

保留必要的辅因子与金属

# removeHeterogens 会无差别删除所有杂原子,包括必需的辅因子。
# 若需保留,应先手工分离,修复后再合并。

from Bio.PDB import PDBParser, PDBIO, Select

class KeepCofactors(Select):
    KEEP = {"ZN", "MG", "MN", "FE", "CA", "HEM", "NAD", "FAD", "ATP", "SAM"}
    def accept_residue(self, res):
        return res.get_resname().strip() in self.KEEP

parser = PDBParser(QUIET=True)
st = parser.get_structure("x", "1m17.pdb")
io = PDBIO(); io.set_structure(st)
io.save("cofactors.pdb", KeepCofactors())

# 修复蛋白后,再把 cofactors.pdb 的内容合并回去
# (注意原子编号与链标识的一致性)

补 loop 的重要提醒

PDBFixer 补的缺失 loop 是用简单几何方法生成的,不是预测出来的真实构象。它能让拓扑完整、模拟不炸,但那段 loop 的具体构象不可信:

  • 缺失 loop 远离结合位点 → 补上即可,不影响结论;
  • 缺失 loop 就在结合位点旁边不要直接信任补出来的构象。应改用同源建模、AlphaFold 预测(该区域通常 pLDDT 较低,本身就是提示),或做 loop 精修,并对补出的构象做充分采样。

修复后的检查清单

from openmm.app import PDBFile, ForceField, Modeller
from openmm import LangevinMiddleIntegrator, unit
import openmm.app as app

# 1) 结构完整性:能否被力场识别(能建体系说明拓扑正确)
pdb = PDBFile("receptor_fixed.pdb")
ff = ForceField("amber14-all.xml", "amber14/tip3pfb.xml")
try:
    system = ff.createSystem(pdb.topology)
    print("✓ 拓扑正确,力场可识别")
except Exception as e:
    print("✗ 拓扑有问题:", e)

# 2) 能量最小化,检查是否有严重原子重叠
integrator = LangevinMiddleIntegrator(300*unit.kelvin, 1/unit.picosecond,
                                      2*unit.femtoseconds)
sim = app.Simulation(pdb.topology, system, integrator)
sim.context.setPositions(pdb.positions)
e0 = sim.context.getState(getEnergy=True).getPotentialEnergy()
sim.minimizeEnergy(maxIterations=500)
e1 = sim.context.getState(getEnergy=True).getPotentialEnergy()
print(f"能量: {e0} → {e1}")
# 初始能量极高(如 1e6 kJ/mol 以上)说明有原子重叠

# 3) 目视检查(务必做)
#    用 PyMOL 或 NGLView 看一遍,重点看补出来的部分
  • 确认该保留的金属、辅因子还在;
  • 确认结合位点残基完整、质子化态合理;
  • 确认没有链断裂或原子位置异常;
  • 若用于 MD,先跑短时间约束模拟确认体系不炸。

常见坑与提示

  • removeHeterogens 会删掉共晶配体与辅因子,需要的要先单独分离出来
  • 补出的 loop 构象不可信,位于结合位点附近时必须另行建模;
  • 组氨酸质子化态影响最大,关键位点人工核对;
  • 修复后必须做能量最小化 + 目视检查,不能直接进入对接。

延伸资源