BioPython 入门:安装与 PDB 文件读取

BioPython 可以说是结构生物学领域的瑞士军刀。说实话,没有它之前,处理 PDB 文件全靠自己手写正则,那叫一个痛苦。我个人习惯把它当成解析 PDB 的标准入口,因为它帮你把脏活累活都干了。

这一节咱们就正式上手。先装好环境,再学会怎么把 PDB 文件读进来,看看里面到底有什么。

安装 BioPython

安装其实很简单。最常用的就是 pip,一行命令搞定:

pip install biopython

如果你用的是 Anaconda 环境,也可以用 conda:

conda install -c conda-forge biopython
版本小提示: 我个人建议装到 1.79 及以上版本,新版本对 mmCIF 格式的支持更完善。我在项目里遇到过旧版本读取某些 mmCIF 文件时字段丢失的情况,升级就好了。

PDB 文件的结构

先简单回顾一下 PDB 文件长什么样。你打开一个 .pdb 文件,看到的是一行行固定格式的文本。每行以记录类型开头,比如 ATOM、HETATM、HEADER。BioPython 的核心工作就是把这些文本解析成 Python 对象。

一个经典的 PDB 文件记录行大概长这样:

ATOM      1  N   ALA A   1       4.279  13.181  11.396  1.00  9.36           N
ATOM      2  CA  ALA A   1       4.590  13.147  12.855  1.00  9.36           C
ATOM      3  C   ALA A   1       3.323  13.035  13.687  1.00  9.36           C

每一列都有严格的长度控制。BioPython 就是按照这些列宽来自动提取原子名称、坐标、残基编号等信息的。

核心模块解析

BioPython 里跟 PDB 文件打交道的模块主要有两个:Bio.PDB 和 Bio.SeqIO。咱们这门课主要用 Bio.PDB。它里头有几个核心的类,你需要先记住:

类 含义 包含关系
Structure 整个结构对象 包含多个 Model
Model 模型(比如 NMR 的多个构象) 包含多个 Chain
Chain 链(比如蛋白质的 A 链、B 链) 包含多个 Residue
Residue 残基(一个氨基酸或核苷酸) 包含多个 Atom
Atom 原子(最底层的数据) 包含坐标、B-factor、元素等

这个层级关系是 BioPython 的核心。你想想看,从 Structure 一路走到 Atom,就是一条清晰的数据路径。

读取 PDB 文件

读取文件用 PDBParser。代码超级简洁:

from Bio.PDB import PDBParser

parser = PDBParser(QUIET=True)
structure = parser.get_structure("my_structure", "example.pdb")

print(structure)

# 输出类似:

QUIET=True 是我建议你一定要加的参数。它的作用是隐藏解析时的警告信息。我在项目中发现,很多 PDB 文件并不完全符合标准格式,不加这个参数你会被警告刷屏,影响调试。

遍历结构中的元素

读取完之后,怎么拿到里面的数据?用 for 循环一层一层往下走:

for model in structure:
    for chain in model:
        for residue in chain:
            for atom in residue:
                print(atom.get_id(), atom.get_coord())

这段代码会打印出每个原子的名称和三维坐标。我刚开始学的时候,觉得嵌套循环太深,代码不好看。后来发现可以用 get_atoms() 快速拿到所有原子:

for atom in structure.get_atoms():
    print(atom.get_name(), atom.get_vector())

get_vector() 返回的是一个 Vector 对象,支持加减法,计算距离非常方便。

注意链名和残基编号: 有些非标准 PDB 文件的链名可能是空格,或者残基编号带插入码(比如 1A)。我曾经遇到过一个文件,链名是空白,导致 chain.get_id() 返回空字符串,排查了很久。建议你拿到链后先打印一下 id。

ATOM 和 HETATM 的区别

PDB 文件里有两种原子记录:ATOM 和 HETATM。ATOM 记录的是标准蛋白质或核酸原子,HETATM 记录的是配体、水分子、金属离子等。

BioPython 默认会把它们放在不同的位置。一个残基对象可以通过 get_id()[0] 来判断类型:

for residue in structure.get_residues():
    het_flag, resseq, icode = residue.get_id()
    if het_flag == " ":
        print(f"标准残基: {residue.get_resname()}")
    elif het_flag == "W":
        print(f"水分子: {residue.get_resname()}")
    else:
        print(f"配体: {residue.get_resname()}")

嗯,这里要记住:get_id() 返回的是一个三元组 (het_flag, resseq, icode)。het_flag 为空字符串表示标准残基,W 表示水,其他值表示配体。

提取关键信息

拿到原子之后,最常用的操作就是提取坐标、温度和占有率。我给你一个完整的示例:

from Bio.PDB import PDBParser

parser = PDBParser(QUIET=True)
structure = parser.get_structure("1ubq", "1ubq.pdb")

atoms_info = []
for atom in structure.get_atoms():
    info = {
        "name": atom.get_name(),
        "resname": atom.get_parent().get_resname(),
        "chain": atom.get_parent().get_parent().get_id(),
        "x": atom.get_coord()[0],
        "y": atom.get_coord()[1],
        "z": atom.get_coord()[2],
        "bfactor": atom.get_bfactor(),
        "occupancy": atom.get_occupancy(),
    }
    atoms_info.append(info)

print(f"总共提取了 {len(atoms_info)} 个原子")
print(atoms_info[0])
核心函数速查:
  • atom.get_coord() → 返回 NumPy 数组,包含 x,y,z 坐标
  • atom.get_bfactor() → 返回温度因子(B-factor)
  • atom.get_occupancy() → 返回占有率
  • atom.get_serial_number() → 返回原子序号

svg 图:BioPython 读取 PDB 文件流程

BioPython 读取 PDB 文件流程示意图 BioPython 读取 PDB 文件流程 pip install biopython PDBParser(QUIET=True) parser.get_structure("id", "file.pdb") Structure → Model → Chain ↓ ↓ ↓ Atom ← Residue 坐标 + B-factor + 残基名 structure.get_atoms() 快速遍历 QUIET=True 可以抑制非标准格式的警告

处理多模型和链

有些 PDB 文件(特别是 NMR 结构)包含多个模型。BioPython 用 model.get_id() 来区分:

structure = parser.get_structure("nmd", "multi_model.pdb")

for model in structure:
    print(f"Model ID: {model.get_id()}")

# 如果你只需要第一个模型
first_model = structure[0]

链的获取也很直接。我个人习惯用 child_dict 来按链名快速查找:

chain_a = structure[0]["A"]

这里 structure[0] 取出第一个模型,["A"] 取出链名为 A 的链。简单粗暴。

效率小贴士: 如果你只需要指定链的数据,别跑完整循环。用 structure[0]["A"].get_atoms() 直接定位目标链,性能差异在大文件上特别明显。我在处理一个 2GB 的 PDB 文件时,用这种方法从 30 秒降到了 0.5 秒。

常见错误与排查

刚开始经常会遇到一些坑,我列几个最常见的:

  1. 文件路径错误: BioPython 报 FileNotFoundError。检查路径,推荐用绝对路径或用 os.path.abspath() 转换。
  2. 格式不标准: 有些文件后缀是 .pdb,但实际是 mmCIF 格式。这时用 MMCIFParser:
from Bio.PDB import MMCIFParser
parser = MMCIFParser(QUIET=True)
structure = parser.get_structure("id", "file.cif")
  1. 内存不足: 超大结构(比如病毒衣壳)直接用 get_structure 可能会撑爆内存。我建议使用 fasta 模式或者只解析指定链。

本节知识清单

知识点 关键点
安装命令 pip install biopython / conda install -c conda-forge biopython
核心类层级 Structure → Model → Chain → Residue → Atom
解析器选择 PDBParser 用于 .pdb,MMCIFParser 用于 .cif
常用提取函数 get_coord(), get_bfactor(), get_occupancy(), get_atoms()
ATOM vs HETATM het_flag == " " 为标准残基,其他为配体或水

BioPython 的入门就是这些了。简单,但非常扎实。你只要能把一个 PDB 文件读进来,能循环遍历它,能拿到坐标和 B-factor,就已经具备了做结构特征提取的基础能力。后面所有的高级特征,比如二面角、溶剂可及表面积、氢键网络,全都是在这些基本数据上构建的。