ProLIF(Protein-Ligand Interaction Fingerprints)与 PLIP 的区别在于定位:PLIP 生成人读的报告,ProLIF 生成机器可分析的指纹。这个差别让 ProLIF 特别适合批量比较与MD 轨迹分析。
什么是相互作用指纹
# 把「配体与蛋白形成了哪些相互作用」编码成向量
#
# 结构:
# 每个「残基 × 相互作用类型」组合是一个位
# 有该相互作用 = 1,没有 = 0
#
# 例:
# ASP86.Hydrophobic = 0
# ASP86.HBAcceptor = 1
# MET93.Hydrophobic = 1
# MET93.HBDonor = 1
# PHE80.PiStacking = 1
# ...
#
# 用途:
# 1) 比较两个姿势的结合模式是否相同
# → 计算 Tanimoto 相似度
# 2) 对大量对接结果聚类
# → 找出有几种不同的结合模式
# 3) 分析 MD 轨迹中相互作用的稳定性
# → 每一帧算一次,得到「占有率」
# 4) 作为机器学习的特征
#
# 关键优势:
# 指纹是定长向量 → 可以直接做数值计算
# 而 PLIP 的文本报告需要解析
基本用法
pip install prolif
import prolif as plf
import MDAnalysis as mda
# 从 PDB + SDF 分析对接结果
u = mda.Universe("receptor.pdb")
protein = plf.Molecule.from_mda(u.select_atoms("protein"))
poses = list(plf.sdf_supplier("docked_poses.sdf"))
fp = plf.Fingerprint([
"Hydrophobic", "HBDonor", "HBAcceptor",
"PiStacking", "Anionic", "Cationic",
"CationPi", "PiCation", "XBDonor", "MetalAcceptor",
])
fp.run_from_iterable(poses, protein)
df = fp.to_dataframe()
print(df)
# 行 = 姿势,列 = (残基, 相互作用类型) 的多级索引
# 转成位向量做相似性计算
bv = fp.to_bitvectors()
from rdkit import DataStructs
sim = DataStructs.TanimotoSimilarity(bv[0], bv[1])
print(f"姿势 0 与 1 的相互作用相似度: {sim:.3f}")
MD 轨迹分析:占有率
# 这是 ProLIF 最有价值的应用
#
# 静态结构只告诉你「某一瞬间有什么相互作用」,
# 而 MD 告诉你「这个相互作用有多稳定」
import MDAnalysis as mda
import prolif as plf
u = mda.Universe("topology.pdb", "trajectory.dcd")
ligand = u.select_atoms("resname LIG")
protein = u.select_atoms("protein and byres around 12 group lig",
lig=ligand)
fp = plf.Fingerprint()
fp.run(u.trajectory[::10], ligand, protein) # 每 10 帧分析一次
df = fp.to_dataframe()
# 计算每个相互作用的占有率
occupancy = df.mean() * 100
occupancy = occupancy[occupancy > 0].sort_values(ascending=False)
print(occupancy.head(20))
# 判读:
# 占有率 > 80% 稳定的核心相互作用 → 设计中必须保住
# 占有率 40~80% 中等稳定
# 占有率 < 20% 瞬时接触 → 在静态结构中看到可能是偶然
#
# 这解决了一个真实问题:
# 共晶结构中看到的某个氢键,可能只是晶体中的
# 一个构象快照,在溶液中并不稳定
# → 基于它做设计会失败
# 可视化
fp.plot_barcode() # 时间轴上的相互作用条形码
fp.plot_lignetwork(poses[0], kind="frame") # 交互式网络图
用于对接结果的筛选
# 场景:有 5000 个对接姿势,想筛出
# 「复现了关键相互作用」的那些
import prolif as plf
from rdkit import DataStructs
# 1) 先分析共晶配体,得到参考指纹
ref_pose = list(plf.sdf_supplier("crystal_ligand.sdf"))
fp_ref = plf.Fingerprint()
fp_ref.run_from_iterable(ref_pose, protein)
ref_bv = fp_ref.to_bitvectors()[0]
ref_df = fp_ref.to_dataframe()
# 2) 找出参考中的关键相互作用(如铰链区)
key_interactions = [
("MET793.A", "HBAcceptor"), # 激酶铰链区的典型氢键
("MET793.A", "HBDonor"),
]
# 3) 批量分析对接姿势
fp_dock = plf.Fingerprint()
fp_dock.run_from_iterable(docked_poses, protein)
dock_df = fp_dock.to_dataframe()
dock_bv = fp_dock.to_bitvectors()
# 4) 两种筛选标准
# (a) 整体相似度
sims = [DataStructs.TanimotoSimilarity(ref_bv, bv) for bv in dock_bv]
# (b) 硬性要求:必须有某个关键相互作用
def has_key(row):
return any(row.get(k, False) for k in key_interactions
if k in dock_df.columns)
keep = [i for i, (s, (_, row)) in enumerate(zip(sims, dock_df.iterrows()))
if s > 0.5 and has_key(row)]
print(f"保留 {len(keep)}/{len(dock_bv)} 个姿势")
# 这是【独立于打分函数】的筛选维度 —— 价值很高(见 096)
ProLIF 与 PLIP 的选择
| PLIP | ProLIF | |
|---|---|---|
| 输出 | 人读报告 | DataFrame / 位向量 |
| 单结构详细分析 | 更好(报告详尽) | 可以 |
| 批量比较 | 需自己解析 | 原生支持 |
| MD 轨迹 | 不直接支持 | 原生支持 |
| 与 RDKit 集成 | 弱 | 强 |
| 水桥检测 | 支持 | 需额外配置 |
| 可视化 | PyMOL 会话 | 网络图、条形码 |
实践中两者常配合使用:PLIP 做单个复合物的深入解读,ProLIF 做批量与轨迹分析。
使用注意
- 需要正确的氢原子:氢键判断依赖氢的位置,输入结构必须已加氢(见 105《PDBFixer》);
- MDAnalysis 的选择语法要写对:选错原子组会得到空结果或错误结果,先打印选中的原子数确认;
- 轨迹分析的帧间隔:全帧分析很慢,通常每 10~50 帧取一帧就够;
- 指纹的可比性:不同体系的指纹长度与列不同,跨体系比较需要对齐列;
- 相互作用定义可调:
plf.Fingerprint可以传入自定义参数调整距离/角度阈值。
关键要点
- 指纹是定长向量,可直接做相似度计算、聚类与机器学习特征;
- MD 占有率分析是它最有价值的能力——揭示共晶中看到的相互作用是否真的稳定;
- 用「必须复现关键相互作用」筛选对接结果,是独立于打分函数的判据;
- PLIP 做单结构深入解读,ProLIF 做批量与轨迹分析,两者配合使用。
延伸资源
- PLIP:108《PLIP》;MDAnalysis:129《MDAnalysis 分析轨迹》;
- 姿势验证:096《Binding Pose》;MD 入门:123《分子动力学 MD 入门》。