4. pLDDT 在 PDB 文件中的存储:B-factor 字段的奥秘归纳总结

好,我们直接进入正题。

你可能已经猜到,AlphaFold 产出的 PDB 文件里,那个原本用来描述原子热运动程度的 B-factor 字段,被“挪用”来存储 pLDDT 分数了。为什么是 B-factor?说白了,PDB 格式是几十年前设计的,当时谁能想到有一天我们会用深度学习预测蛋白质结构?所以没有预留“置信度”这个字段。既然 B-factor 是现成的、每个原子都有的“浮点数插槽”,那就它了——天选打工人。

我个人习惯,拿到一个 AlphaFold 的 PDB 文件,第一件事就是看看 B-factor 列的分布。这比你盲看坐标要直观得多。

4.1 B-factor 与 pLDDT 的映射规则

PDB 文件里,ATOM 记录的第 61-66 列(没错,固定列宽格式)就是 B-factor。正常情况下它是 0 到 100 之间的实数。AlphaFold 直接把它填成 pLDDT 值,单位是 0-100,不是温度单位的 Ų。

这里有一个非常重要的细节,我刚开始处理数据时就被坑过:

⚠ 高能预警
AlphaFold 官方代码在写 B-factor 时,会用 100 - pLDDT 取补?
不是! 它写的就是原始的 pLDDT 分数,0-100,值越高置信度越高。

看看典型的 PDB 文件片段:

ATOM      1  N   MET A   1       8.375  20.371  22.735  1.00 85.32           N  
ATOM      2  CA  MET A   1       8.404  21.367  21.648  1.00 84.91           C  
ATOM      3  C   MET A   1       9.779  21.502  21.048  1.00 84.02           C  
ATOM      4  O   MET A   1      10.540  20.525  21.074  1.00 83.74           O  
...

倒数第二列 85.32、84.91 就是 B-factor,也就是 pLDDT。这个残基置信度很高,都在 80 以上。你看,读取完全不费劲。

4.2 如何在代码中提取 B-factor 作为 pLDDT

既然 B-factor 就是 pLDDT,问题就变成:怎么优雅地把它读出来?

我一般用 Python,结合 Bio.PDB 或 gemmi。我给你三个层次的做法:

4.2.1 按残基提取(标准做法)

from Bio.PDB import PDBParser

parser = PDBParser(QUIET=True)
structure = parser.get_structure("model", "alphafold_model.pdb")

for model in structure:
    for chain in model:
        for residue in chain:
            # 计算残基级平均 pLDDT
            b_factors = [atom.get_bfactor() for atom in residue if atom.get_bfactor() > 0]
            if b_factors:
                avg_plddt = sum(b_factors) / len(b_factors)
                print(f"{residue.get_id()[1]}  {avg_plddt:.1f}")

注意,我加了个 `if atom.get_bfactor() > 0` 的过滤,后面会讲为什么需要它。

4.2.2 按原子级别保留

有些场景你需要所有原子的置信度——比如做局部柔性分析。这时直接全量取:

atom_plddts = []
for atom in structure.get_atoms():
    atom_plddts.append(atom.get_bfactor())

4.2.3 用 gemmi 快速读

我个人偏好 gemmi,因为它解析超级快,而且直接暴露 B-factor 为数组:

import gemmi

st = gemmi.read_structure("alphafold_model.pdb")
chain = st[0][0]  # 第一个模型,第一个链

for res in chain:
    b = res[0].b_iso  # 第一个原子的 B-factor
    print(f"{res.seqid.num}  {b:.1f}")

这种方法大约能快 5-10 倍,适合批量处理几千个 PDB 文件。

4.3 B-factor 字段的“坑”:数值异常与缺失

说了这么多好的,现在我来讲讲我踩过的坑。

第一,pLDDT 小于 30 的情况。
AlphaFold 会输出低置信度的区域,比如 loops。B-factor 可能是 20、15、甚至接近 0。这时候你不能直接拿来当温度因子用,否则动力学分析会出错。解决方案:只把 B-factor 当 pLDDT 解读,不要当真正的 B-factor。

第二,有些地方 B-factor 是 0.00。
这在 AlphaFold 多聚体预测里常见。某个残基完全不可信,AlphaFold 直接给了 0.00。这不是 bug,是特征。我曾经在一批数据里没做筛选,直接拿 B-factor 和实验结构比对了,结果在无序区域偏差很大。后来加了一个阈值:pLDDT < 50 的区域不参与结构对齐。

第三,PDB 文件里的整数存储问题。
PDB 格式第二版规定 B-factor 字段是 6 个字符,含小数点。AlphaFold 为了省空间,有时会输出 85.32 四位有效数字。解析时如果按固定宽度强读,可能会截断最后一位。建议用列宽方式读(61-66),别用逗号分隔。

💡 实用技巧
如果 PDB 文件是 AlphaFold 输出的但 B-factor 全部是 0.00?
极大概率你用的是旧版 AlphaFold(v2.0 之前)或自行修改的代码。升级到 v2.3+,或者从 pickle 结果文件里提取 pLDDT 自己写到 B-factor。

4.4 B-factor → pLDDT 的语义变化对照表

B-factor 数值 原始含义(实验结构) AlphaFold 映射含义(pLDDT) 操作建议
> 90 低温、有序、高分辨 极高置信度 可直接用于建模
70 - 90 中等温度因子 高置信度 结构可信,适用于对接
50 - 70 较无序、运动大 中等置信度 需要谨慎,建议结合其他方法验证
< 50 高度无序、低分辨 低置信度 建议删除或标记为不可靠

对,这就是 B-factor 字段在 AlphaFold 语境下的“语义翻车”。你拿到一个蛋白质,B-factor 20 的区域,不是它真的在疯狂振动,而是 AlphaFold 没把握。这个观念一定要转过来。

4.5 从 B-factor 可视化 pLDDT 的流程

最后,我来把整个逻辑串成一张图,方便你直接复用。一张图看懂 B-factor 到 pLDDT 的转换与可视化路径:

pLDDT 在 PDB 文件中的读取与可视化流程 PDB 文件 解析 ATOM 第 61-66 列 → B-factor 值 pLDDT ≥ 70 (高置信度) pLDDT < 70 (低/中置信度) B-factor → 温度因子映射(蓝色) B-factor → 温度因子映射(红色) 最终输出:图谱 + 置信度报告 关键:B-factor 直接就是 pLDDT,无需做任何转换

你看,整个流程其实就两步:读 B-factor → 按 pLDDT 阈值渲染颜色。但第二步里藏着最多细节。

我个人建议,在提取 B-factor 之后,立刻做一个统计直方图。你可以在 Python 里用 matplotlib,或者直接用 PyMOL 的 `spectrum b` 命令来看分布。如果直方图大部分集中在 90-100,说明这个模型很可靠;如果大量在 50 以下,嗯……那你要警惕了。

✔ 一句话总结本章:
AlphaFold PDB 文件的 B-factor 字段就是 pLDDT 分数,数值范围 0-100。读它、理解它、按阈值分类它——你就已经掌握了 80% 的结构可靠性评估。