3. PDB数据结构与字段含义
PDB格式,说白了就是蛋白质结构的“通用语言”。我在刚接触这个领域时,最先面对的就是那堆密密麻麻的文本行。不弄清楚每一列是什么,后续工作根本无从谈起。
这一章我们来拆解PDB文件中最重要的两类记录:ATOM和HETATM,以及残基命名规则、字段含义和粒度层次。
3.1 PDB文件的基本框架
一个PDB文件是由多条记录按顺序组成的。每条记录都有固定的列偏移,早期标准每列都有专属用途。
下面是一个简化版的PDB文件片段——只看结构层次:
HEADER EXTRACELLULAR MATRIX 29-JAN-98 1A3I
TITLE STRUCTURE OF THE INTEGRIN BINDING PROTEIN DELAFIN
COMPND MOL_ID: 1; MOLECULE: DELAFIN; CHAIN: A, B
ATOM 1 N ALA A 23 10.525 37.119 11.579 1.00 19.59 N
ATOM 2 CA ALA A 23 10.419 36.740 10.159 1.00 18.30 C
ATOM 3 C ALA A 23 9.221 35.817 9.936 1.00 16.50 C
HETATM 200 O HOH A 45 11.200 38.500 12.000 1.00 20.00 O
TER 400 ALA A 23
END
嗯,这里要注意:ATOM 记录的是标准氨基酸的原子,HETATM 则用于非标准分子。我遇到过不少新手把这个搞混,导致对接计算时出了大问题。
3.2 ATOM记录——核心中的核心
一条 ATOM 记录共 12 个固定字段。我习惯用一张对照表来记忆它们的位置:
| 字段 | 列位置 | 描述 | 示例 |
|---|---|---|---|
| 记录类型 | 1-6 | 固定为「ATOM」或「HETATM」 | ATOM |
| 序号 | 7-11 | 原子编号,按出现顺序计数 | 1 |
| 原子名称 | 13-16 | 原子名称,如 CA、CB、N | N |
| 残基名称 | 18-20 | 三字母氨基酸代码 | ALA |
| 链标识 | 22 | 单字母链 ID | A |
| 残基号 | 23-26 | 在链内的序列编号 | 23 |
| X 坐标 | 31-38 | 埃格斯特朗单位 | 10.525 |
| Y 坐标 | 39-46 | 同上 | 37.119 |
| Z 坐标 | 47-54 | 同上 | 11.579 |
| 占位因子 | 55-60 | 位置占有率(0~1) | 1.00 |
| 温度因子 | 61-66 | B factor,热运动参数 | 19.59 |
| 元素符号 | 77-78 | 元素周期表符号 | N |
那这六列坐标都记录了什么呢?其实就是该原子在三维空间中的精确位置。我做对接时经常遇到 占位因子 不等于 1.0 的情况——这意味着该原子在晶体中有两种可能位置。
个人习惯:解析时我从不依赖空格分割,而是按固定列截取字符串。原因是有些字段是左对齐、有些是右对齐,split 后很容易错位。
3.3 HETATM 与残基命名
有一次我在筛选 PDB 文件时,发现一个蛋白结构里竟然有 200 多个水分子。这些水就属于 HETATM 记录。两者基本一模一样,就差在记录名称上。
HETATM 适用于:
- 水分子(
HOH) - 配体(如 ATP、NAD、抑制剂)
- 金属离子(如 Zn²⁺、Mg²⁺)
- 修饰过的残基(如 MSE)
残基命名同样有讲究:
| 类型 | 示例 | 说明 |
|---|---|---|
| 标准氨基酸 | ALA, GLY, LYS | 20 种常见氨基酸的三字母缩写 |
| 非标准残基 | MSE, CSD | 修饰氨基酸,常见于晶体学衍生 |
| DNA/RNA | DA, DC, U, A | 核酸碱基,D 前缀表示 DNA |
| 配体/小分子 | ATP, NAD, HOH | PDB 组分字典定义的代码 |
你想想看:如果把一个 MSE(硒代甲硫氨酸)当作标准 MET 处理,你的能量计算就会完全跑偏。我早期就吃过这个亏,后来学乖了,先在处理流程中加入残基类型白名单检查。
3.4 原子名称与字段细节
原子名称的规则其实藏着大学问。比如 CA 可能是 Cα(主链碳),也可能是钙离子。怎么区别?看记录类型就知道了——钙离子的记录一定是 HETATM,而不是 ATOM。
常见原子名称格式:
N,CA,C,O—— 主链四大件CB,CG,CD1—— 侧链原子OXT—— C 端氧原子1H,2H—— 氢原子(多用数字前缀区分)
坑点:我曾经在对接时把 HETATM 里的金属离子坐标直接拼进蛋白结构,结果计算出的结合自由能全是 NaN。后来发现是元素符号字段被截断——Zn 只取了 Z,影响了原子半径查找。
记住:元素符号 在 77-78 列,如果只有 1 个字符,第 78 列一定是空格。
3.5 知识框架图
下面这张 SVG 图展示了本章核心知识点之间的层级关系:
3.6 解析实操
你写 Python 脚本时怎么解析?记住两点:一是用 line[12:16].strip() 这种切片方式取原子名,二是用 line[17:20].strip() 取残基名。别偷懒用 split()。
下面是一段我日常用的解析核心代码:
def parse_atom_line(line):
if not (line.startswith("ATOM") or line.startswith("HETATM")):
return None
rec = line[0:6].strip()
atom_serial = int(line[6:11].strip())
atom_name = line[12:16].strip()
alt_loc = line[16].strip()
res_name = line[17:20].strip()
chain_id = line[21].strip()
res_seq = int(line[22:26].strip())
x = float(line[30:38].strip())
y = float(line[38:46].strip())
z = float(line[46:54].strip())
occupancy = float(line[54:60].strip())
b_factor = float(line[60:66].strip())
element = line[76:78].strip()
return {
"record": rec,
"serial": atom_serial,
"name": atom_name,
"alt_loc": alt_loc,
"res_name": res_name,
"chain": chain_id,
"res_seq": res_seq,
"x": x, "y": y, "z": z,
"occupancy": occupancy,
"b_factor": b_factor,
"element": element
}
关键提醒:残基号可能带插入码(如 23A),那时 line[22:26] 里含有字母。遇到这种情况,序列号要用 line[22:27].strip(),并单独提取字母部分做排序用。
3.7 记录类型对照总结
下面这个表就是日常区分 ATOM 和 HETATM 的快速参考:
| 特征 | ATOM | HETATM |
|---|---|---|
| 记录类型字符串 | ATOM | HETATM |
| 包含的分子 | 标准 20 种氨基酸、核酸主链 | 水、配体、非标准残基、离子 |
| 异常处理建议 | 缺少时优先补全(后续章节讲) | 缺失时通常直接丢弃或单独处理 |
| 占位因子范围 | 通常为 1.0 | 可能出现 0.3~1.0 的位置无序 |
| 在解析中的角色 | 组成蛋白主链、侧链 | 外部小分子、环境 |
个人技巧:处理前先把所有 HETATM 中的水行单独列出来,将它们转存到 WATER 组里,能大幅减少后续对接时的计算量。
这一章的要点就是这些。记牢字段的列偏移和命名规则,你解析 PDB 文件就不再是靠感觉胡乱切字符串了。