3. PDB文件格式解析:原子记录、残基链标识与六列坐标系统

PDB文件,说白了就是蛋白质结构的“通用语言”。无论是X-ray、NMR还是冷冻电镜解析出来的结构,最后都会被记录成这种固定格式的纯文本文件。我这些年清洗过的PDB文件少说也有几万套,发现大多数人栽的坑,往往就是没搞懂那几行原子记录是怎么写的。

本章咱们就把PDB文件的原子记录这块彻底掰开揉碎。你理解了ATOM行和HETATM行,就等于拿到了结构清洗的入场券。

3.1 ATOM与HETATM:两条核心记录行

PDB文件里最重要的,就是ATOM和HETATM开头的行。ATOM记录蛋白质自身的原子,HETATM记录配体、水分子、金属离子等“额外”原子。两者格式完全一样,靠这么一个小区别就把“蛋白质”和“配体”分开了。

一个关键经验:有些工具会严格按照ATOM/HETATM来区分蛋白和配体。如果你把配体放进了ATOM记录,或者把蛋白质残基写成了HETATM,对接的时候直接报错。别问我怎么知道的,我被这个问题坑过不止一次。

咱们来看看标准的记录格式。每条原子记录占一整行,80个字符,字段固定。下面这个例子展示了两条典型的原子行:

ATOM     12  N   ALA A   1      11.265  14.431   6.995  1.00  0.00           N
HETATM   34  C1  LIG B   1      15.342  22.178   9.883  1.00  0.00           C

这两行虽然只占了整行的一小部分,但里面藏了十几个字段。我把这些字段拆开介绍一下:

列位置 字段 说明 长度/格式
1-6 记录类型 ATOM或HETATM,右对齐,我习惯用格式化输出补足空格 字符6
7-11 原子序号 从1开始顺序编号,不建议用这个做原子标识,因为清洗后可能乱 整数5
13-16 原子名称 标准氨基酸用IUPAC命名(如CA、CB、N、O),配体常用PDB自定义名 字符4,左对齐
17 备选位置 默认空格或'.';多构象时标'A','B'等。我建议清洗时保留主构象 字符1
18-20 残基名称 三字母编码,如ALA、LIG、HOH 字符3,右对齐
22 链标识 单字符链ID,如A、B,空格表示单链 字符1
23-26 残基编号 整数,支持负号 整数4
27 插入码 处理残基插入时的标记,如'A' 字符1
31-54 X Y Z坐标 正交坐标,单位埃 每个浮点8.3
55-60 占有率 通常1.00,不全占时小于1 浮点6.2
61-66 温度因子 B因子,单位Ų 浮点6.2
73-80 元素符号 右对齐,如C、N、O、S、Fe 字符2,可选

你注意看第12列和第21列,这两列是 固定的空格。我见过不少人写代码解析PDB时没处理好这些空格的偏移,导致原子名称和残基名称读成了一坨。嗯,解析PDB最好用结构化库,比如BioPython,别自己写切片,容易翻车。

3.1.1 备选位置的处理

备选位置字段(第17列)是个容易忽略但非常关键的细节。高分辨率的结构里,部分残基会有两种甚至三种构象。PDB文件会用同一个原子序号、不同的备选位置字母来记录这些构象。

一个我曾经踩过的坑:我曾经处理一套2.0Å的结构,没注意备选位置字段。结果一个残基出现了两个CA原子,坐标还差1.5Å。对接的时候能量死活不对,因为蛋白内部出现了“原子打架”。后来加了一步备选位置过滤,默认只保留A构象,问题解决。

3.2 链标识与残基编号:别搞混了这些标识

链标识(Chain ID)是个单字符,用来区分蛋白复合物中的不同链。比如抗体-抗原复合物,可能重链是H、轻链是L、抗原是A。残基编号则是链内的顺序号。

我建议你在清洗流程里,一定要把 链标识 + 残基编号 + 插入码 三者联合作为残基的唯一键。只看残基编号是不安全的,因为不同的链可能有相同的编号。

下面这张表汇总了常见的标识符和它们的作用:

标识符 所在位置 作用说明 处理建议
链标识 第22列 区分不同多肽链 保留原始链ID,清洗时不要随意重命名
残基编号 第23-26列 链内顺序编号,可能为负(如配体) 允许负号,解析时注意整数转换
插入码 第27列 表示插入残基 序列结构对齐时需展开为序列间隙
原子名称 第13-16列 原子类型和位置(如CA是Cα) 清洗时推荐映射为标准IUPAC名称
备选位置 第17列 多构象标记 默认保留备选位置A,丢弃其余
一个小技巧:手写脚本解析时,我习惯把链标识和残基编号拼接成一个字符串作为键,比如"A_123"。这样既能保证唯一性,又方便调试时定位问题。pandas里用这个键做groupby,能直接统计每个残基的原子数量,快速发现异常。

3.3 六列坐标系统:真相都在这些数字里

PDB里最核心的数据就是第31到54列的X、Y、Z坐标。三组浮点数,每组占8列,定点格式8.3。什么意思?就是总宽8位,小数部分3位。这决定了PDB坐标的理论精度是0.001Å。

但实际上,我拿到的大部分结构的坐标精度远达不到这个量级。X-ray结构的坐标误差通常在0.1-0.3Å,低温电镜的精度更低。你想想看,用8.3格式去记录本来就不可靠的坐标,有点“过剩包装”的意思。不过规则就是规则,8.3格式带来的好处是:所有原子行对齐,解析简单。

我最早学PDB解析时,曾被这六个数字“骗”过。我之前以为坐标行只包含X、Y、Z就完了,后来才知道,在标准PDB里,这六列之外的52-54列其实并没有定义新的坐标。真正需要我关心的,就是那六个数字。

另外,PDB的坐标系统是 正交坐标,单位是Å。你可能会问:那晶胞里的分数坐标呢?嗯,分数坐标存在CRYST1记录里。如果你做的是晶体结构的对称操作,就需要先用CRYST1里的晶胞参数把正交坐标转成分数坐标,做完变换再转回去。

一个实用原则:清洗时只看正交坐标。除非你要做晶胞扩展或者对称体生成,否则不要碰分数坐标。坐标单位统一用Å,如果遇到其他单位(极少),先做换算。

3.3.1 占有率与B因子

坐标行后面的占有率(occupancy)和温度因子(B-factor)也是清洗时要留意的东西。占有率低于0.5的原子,说白了就是基本“看不见”的原子,我建议删掉。B因子过高的原子(比如超过60),说明这个原子在晶体里飘来飘去,清洗时也可以考虑剃掉。

但这里有个度。有些柔性的loop区域B因子整体偏高,你如果全删了,蛋白结构就断了。我一般保留B因子中位数±2倍标准差范围内的原子,超出范围的标记一下,不直接删除。

3.4 一张图搞懂PDB记录结构

下面这张SVG图,把PDB文件中原子相关的核心结构串联了一下。看完它,你应该能理解记录行、字段偏移和它们之间的关系。

PDB文件原子记录核心结构 记录类型 ATOM / HETATM 原子标识 序号 + 名称 残基与链 残基名 + 链ID + 编号 坐标 X Y Z (Å) 质量因子 Occupancy / B 字段偏移(以PDB标准80列格式为准) 第1-6列: 记录类型 | 第7-11列: 原子序号 | 第13-16列: 原子名称 | 第18-20列: 残基名称 第22列: 链标识 | 第23-26列: 残基编号 | 第31-54列: X Y Z 坐标 | 第55-66列: 占有率/B因子 解析ATOM/HETATM行 按字段定位切片提取 提取标识信息 链ID + 残基编号 坐标数据提取 X Y Z 三列浮点数 质量过滤 Occ ≥ 0.5 输出清洗后的原子记录结构

3.5 一些实战中的检查清单

每次拿到一个新的PDB文件,我建议你先走一遍下面的快速检查。能帮你避免后面对接、模拟时出现各种莫名其妙的问题。

  • 检查记录类型:ATOM和HETATM是否分对了?配体是否被错误标记为ATOM?
  • 检查备选位置:有没有多构象?是否只保留了主构象?
  • 检查链标识:链ID是否统一?空链标识是否需要补成'A'?
  • 检查残基编号:有没有异常大的编号(如9999)?有没有负数?
  • 检查坐标范围:坐标值是否在合理区间(通常-50到100Å)?有没有极大值(超过1000Å)?
  • 检查占有率:占有率不全为1时,是否做了取舍?
  • 检查元素符号:第77-78列是否缺失或错误?比如Fe写成了FE。
一个我自己项目里用的小脚本思路:先用Python的BioPython读一遍PDB,然后遍历所有原子,把链标识、残基名、残基编号、备选位置和坐标打印出来看一眼。通常5秒就能定位问题。比如:
from Bio.PDB import PDBParser
parser = PDBParser(QUIET=True)
structure = parser.get_structure("test", "1abc.pdb")
for model in structure:
    for chain in model:
        for residue in chain:
            for atom in residue:
                print(chain.id, residue.get_id(), atom.get_name(), atom.get_vector())

PDB文件格式看起来枯燥,但懂了就是懂了。你只需要记住ATOM/HETATM的行结构、链标识和坐标的偏移位置,后面所有的清洗步骤都是在这个基础上做的。

行,这一讲就到这里。多拿几个PDB文件练练手,拆开看看里面的原子记录,你很快就熟了。