前置阅读:
ESP-DNN:ESP-DNN 本地部署实战: 7 年前的图卷积静电势模型一秒复现DFT精度的静电势表面
espsim: espsim 本地部署实测: 给生物电子等排体一个静电势相似度打分
你在做配体筛选时碰到这种情况:用 Glide 出 100 个对接 pose,肉眼看都"对得上"靶点口袋,但用 DFT 算 ESP surface 一查——形状对的那批电场形貌其实完全不同。本想用 espsim 算 ESP 相似度来重打分,却发现 espsim 默认用 Gasteiger 电荷、粗糙,没法反映真实 ESP 形貌。Astex 2019 年发了一篇 J. Med. Chem.介绍了ESP训练模型ESP-DNN,能以"近 DFT 质量"算每个原子的 ESP 电荷,但官方仓库只有 Py2.7 + TF 1.10 + Linux-only PLI 二进制三件套——Windows 上根本装不上。本文带你把这套 2019 年的工具链拆成 Path A(仅 on-atom 重原子)、Path B(重原子 + 氢)、Path C(PLI ground truth:重原子 + 氢 + 孤对 + σ-hole)三路 PQR 生成路径,从而高精度获得ESP电荷,最终用 espsim 在同一套坐标上对比三路 ESP 相似度——量化出"丢掉 off-center 电荷到底损失多少"。
关键词:ESP-DNN、AstexUK、espsim、PQR、off-center 电荷、Python 3.11 迁移、conda 环境隔离
相关教程与核心文献
| 资源 | 链接 | 与本文关系 |
|---|---|---|
| AstexUK/ESP_DNN 仓库 | github.com/AstexUK/ESP_DNN | DNN 模型 + PLI 二进制 + 示例配体 |
| heid-lab/espsim 仓库 | github.com/hesther/espsim | ESP 相似度计算库 |
| Rathi 等,J. Med. Chem.2019, 62, 7383–7397 | 10.1021/acs.jmedchem.9b01129 | ESP-DNN 原始论文 |
| Heid E & Boeckler N,J. Chem. Inf. Model.2022, 62, 4891–4899 | 10.1021/acs.jcim.1c01535 | espsim 原始论文 |
| PLI 文档 (Astex) | github.com/AstexUK/ESP_DNN/blob/master/esp_dnn/ext/pli/params/pli.params | off-center 元素参数表(PLI 必读) |
| Crossref API(DOI 元数据) | api.crossref.org | 引用核验必备 |
一、为什么需要这套组合?
1.1 你遇到的问题
做 SAR 或对接 pose 重打分时,你大概需要这样的指标:两分子的静电势(ESP)形貌有多像。espsim 能算——但 espsim 默认用 Gasteiger 电荷,化学直觉告诉我们:
- Gasteiger 在卤素、芳香 N、酰胺等系统上误差 0.1–0.3 e
- 对 σ-hole、孤对这种"方向性 ESP"几乎不体现
- espsim 论文里也明说"建议用户提供 QM/DNN 电荷以提升精度"
Astex 2019 年发了一篇 ESP-DNN(J. Med. Chem.),能给"近 DFT 质量"的原子 ESP 电荷,但官方仓库默认Python 2.7 + TF 1.10 + 64-bit Linux PLI 二进制——Windows / macOS 根本装不上。
1.2 这套方案解决的核心问题
本文拆三路跑通端到端:
| 路径 | 实现 | 部署难度 | off-center |
|---|---|---|---|
| A | Py3 + TF 2.15 + RDKit 2026,只算 on-atom 电荷,丢 H 与 off-center | 本地 Windows OK | 无 |
| B | Path A 基础上,氢原子用 Gasteiger 补,仍无 off-center | 本地 Windows OK | 无 |
| C | 在 Linux 服务器(如团队 Linux 服务器)跑 AstexUK 原版 PLI 二进制,完整 off-center PQR | 需要 Linux + 服务器 | 有 |
三路共用同一套 3D 坐标,仅电荷不同——espsim 算 ESP 相似度时差异完全来自电荷处理,可单独量化 off-center 损失。
二、Py3 迁移的 7 个实测坑
把 AstexUK 仓库从 Py2.7 + TF 1.10 搬到 Py3.11 + TF 2.15 踩了 7 个坑——这是迁移到现代 Python 时的典型障碍:
| 坑 | Py2 原写法 | Py3 修法 | 影响范围 |
|---|---|---|---|
| 1. NumPiElectrons 位置 | from rdkit.Chem.AtomPairs.Utils import NumPiElectrons | from rdkit.Chem.rdchem import GetNumPiElectrons as NumPiElectrons | atom_features.py 失败 |
| 2. range + list 不可加 | range(1, 19) + [None] | list(range(1, 19)) + [None] | 模块顶层就 raise |
| 3. Py2 pickle 反序列化 | pickle.load(f) | pickle.load(f, encoding='latin1') | 加载 norm_params.pkl 失败 |
| 4. Keras 1.x 引擎 | from keras.engine.topology import Layer | from tensorflow.keras.layers import Layer | graph_conv.py 报 ImportError |
| 5. Adam 在 TF 2.16 移位 | tf.keras.optimizers.Adam | tf.keras.optimizers.legacy.Adam | 模型构建失败 |
| 6. K.batch_dot 在 TF2 静默 | K.batch_dot(d, self_output) | tf.linalg.matmul(d, self_output) | 行为不变但被 deprecation |
| 7. setuptools ≥81 移除 pkg_resources | espsim 0.0.1import pkg_resources | pip install 'setuptools<81' | 整个 espsim import 失败 |
最隐蔽的是 #3——Py2 写出的 .pkl 文件含 str(unicode)而非 bytes,Py3 默认 ASCII 解码,pkl 头几个字节就 raise UnicodeDecodeError,必须加encoding='latin1'。
三、本地安装(Path A + Path B)
环境需求:Python 3.11(TF 2.15 wheel 只到 3.11;3.12+ 装 TF 2.16 会触发别的兼容问题)。消费级 GPU 足够,本机走 CPU 推理 ~150 ms/分子。
# 1. venv uv venv --python 3.11 ~/ESP_DNN_sim_env 2. 依赖 uv pip install --python ~/ESP_DNN_sim_env/Scripts/python.exe --index-url https://pypi.tuna.tsinghua.edu.cn/simple "numpy==1.26.4" pandas xarray "tensorflow==2.15.0" rdkit espsim scipy "setuptools<81"踩坑 #8(Windows 特有):git clone AstexUK/ESP_DNN 在 Windows 上会失败——仓库里有
cif/CON/CON.cif和cif/PRN/PRN.cif两个文件,Windows 把 CON、PRN 当设备保留字(COM1、LPT1 同类),git 拒 checkout。解法:用 tarball(curl codeload)+ zip 解压——zip 文件名内允许 CON/PRN,Linux 上unzip后这两个文件正常落地。
3.1 加载模型验证
import sys; sys.path.insert(0, "~/Desktop/M3/ESP_DNN_sim/esp_dnn_py3") from esp_dnn.predict import MolChargePredictor mcp = MolChargePredictor() # 首次加载 ~10s(解析 h5) print(mcp.model.input_shape) # [(None, None, 64), (None, None, None)]四、Path A — on-atom heavy only
代码路径:MolChargePredictor.write_pqr_block_on_atom_only(pdb_block, dqs)。每个非氢原子的 occupancy 字段写入 DNN 预测电荷,氢原子留 0。20 原子分子输出 20 行 PQR。
用法:
from esp_dnn.predict import MolChargePredictor mcp = MolChargePredictor() dqs = mcp.predict_dqs_from_pdb_block(open("lig1.pdb").read()) pqr = mcp.write_pqr_block_on_atom_only(open("lig1.pdb").read(), dqs) open("lig1.path_a.pqr", "w").write(pqr)五、Path B — on-atom + 氢(Gasteiger backfill)
代码路径:MolChargePredictor.write_pqr_block_with_hydrogens(pdb_block, dqs)。氢原子的电荷用 RDKitComputeGasteigerCharges补。20 原子分子输出 ~40 行(20 重 + ~20 氢)。
为什么不用 DNN 给氢预测?——DNN 只在heavy-only训练(论文里说的),强行把氢也喂给模型超出训练域。Gasteiger 在氢上误差比 heavy 大,但对 ESP 形貌影响有限(氢原子半径小、积分体积占比低)。
六、Path C — PLI ground truth(Linux 服务器)
PLI 二进制(5.3 MB ELF)做的事:在 DNN 给的重原子电荷基础上,根据elements.pli表在孤对 / σ-hole / p 轨道位置再放一个虚拟电荷点。这一步是 Path A/B 缺的"方向性 ESP"来源。
6.1 Linux 服务器部署
# Linux 服务器端(已装 amber26 自带 Python 3.12 + RDKit 2026.3 + TF 2.16) git clone --depth 1 https://github.com/AstexUK/ESP_DNN.git export PLI_DIR=$PWD/ESP_DNN/esp_dnn/ext/pli /opt/amber26/python/bin/python3 scripts/run_path_c.py踩坑 #9:PLI 不带 help flag,
-mode features失败时报"unknown mode"——真因是 PLI_DIR 没设。设对后prepare/features/preplig/score都接受。
6.2 Path C 字节级匹配 Astex 自身 saved 文件
跑出的lig1.path_c.pqr与仓库自带examples/ligands/lig1.mol.pdb.pqr.saveddiff 为空——这是 AtexUK 论文的 ground truth 路径。
七、espsim 三路对比(核心实证)
7.1 实验设计
- 分子集:AstexUK 自带 4 个测试分子(lig1 / lig2 / lig3 / lig1_charged)
- 关键对照:lig1 vs lig1_charged(同骨架、+0.4 总电荷)——电荷判别能力试金石
- 三路 PQR 原子数:
| 分子 | Path A | Path B | Path C |
|---|---|---|---|
| lig1 | 20 | 40 | 63 |
| lig2 | 19 | 40 | 62 |
| lig3 | 20 | 42 | 65 |
| lig1_charged | 20 | 41 | 63 |
Path C 的额外 ~23 行就是 off-center 虚拟原子(Hlp 氮孤对、Hsh 氯 σ-hole 等)。
7.2 ESP sim 数值(Carbo 指标,espsim 重整化到 [0,1])
| 对 | Path C (ground truth) | Path B | Δ(B-C) | Path A | Δ(A-C) |
|---|---|---|---|---|---|
| lig1 vs lig2 | 0.9588 | 0.9419 | +0.017 | 0.9998 | −0.041 |
| lig1 vs lig3 | 0.9274 | 0.8840 | +0.043 | 0.9999 | −0.072 |
| lig1 vs lig1_charged | 0.5751 | 0.9162 | +0.341 | 0.9997 | +0.425 |
| lig1_charged vs lig2 | 0.5375 | 0.9625 | +0.425 | 0.9995 | +0.462 |
| lig1_charged vs lig3 | 0.5080 | 0.9600 | +0.452 | 0.9998 | +0.492 |
Δ(X-C) = 路径 X 的 ESP sim 减 Path C。正数 = 简化让分数变低(真损失),负数 = 简化让分数变高(伪提升)。
7.3 三条不可忽略的发现
(1) Path A 虚高是积分体积 artifact
Path A 在所有 5 对上都跑到 0.999+——不是因为 ESP 表面更匹配,而是 espsim 把 1/r 库仑积分在每个原子的 vdW 球壳内做,丢掉 H 原子等于缩小积分区域,分数自然抬高,但无物理意义。绝对数字不可用,仅可做同次运行的相对排序。
(2) Path B 对中性体系勉强可用
Path B 对中性 vs 中性(lig1/lig2/lig3)成本 +1.7% 到 +4.6%,排序保持不变。可做中性 SAR 内的快速筛选。
(3) Path B 对带电配体彻底失效
lig1 vs lig1_charged:Path C 给 0.5751(正确——这两分子净电荷差 +0.4,ESP 表面显著不同),Path B 给 0.9162(判不出带电差异)。DNN 的apply_charge_correction只对形式电荷原子加 0.4×formal charge 校正,不补 PLI 那套方向性 off-center。所以 +0.4 净电荷在 Path B 里只表现为某个原子上一个微小的额外电荷,ESP 形貌没改——espsim 看不到差异。
八、决策矩阵:什么时候用哪路
| 场景 | Path A | Path B | Path C |
|---|---|---|---|
| 中性 vs 中性 SAR | 仅排序可用 | 推荐 | ground truth |
| 带电 vs 中性判别 | 完全无效 | 失效 | 必需 |
| 带电 vs 带电 | 仅排序可用 | 排序 OK | ground truth |
| 跨体系绝对 ESP sim 数值 | 物理无意义 | ±5% 真值 | truth |
| 速度(每分子) | ~150 ms | ~170 ms | ~10 s(含 PLI round-trip) |
结论:
- 做中性分子 SAR 快速打分 → Path B 够用
- 做带电 vs 中性 / 带电 vs 带电 →必须 Path C
- 论文级、对外汇报 → 永远 Path C
- Path A 仅当你不关心绝对数、只关心同次运行的排序时
九、局限与展望
9.1 当前限制
- Path B 的氢电荷是 Gasteiger 近似——对极化氢(N–H、O–H、amide N–H)误差 ~0.05 e,传播到 ESP sim 约 ±2%
- Path C 强依赖 PLI 二进制——目前是 Linux ELF,macOS / Windows 无法本地跑,必须有 Linux 服务器
- DNN 训练集 10 万分子全是中性(AstexUK 没披露是否含带电样本比例),所以带电分子本身的电荷预测就有系统偏差
- GitHub 仓库的 PLI 是 Astex 公开版(64 MB PLI 数据 + 5.3 MB 二进制 = ~80 MB),off-center 元素参数表可能不是 Astex 内部完整版——论文表 S1 描述了 50 种元素的 off-center 位置/电荷,但仓库
elements.pli未必全部覆盖
9.2 未来方向
- 用 psi4 / OpenFF 直接算 off-center 虚拟位点(不靠 PLI),可在 Windows / macOS 上跑
- 训练 DNN 时补带电样本——A 股公开数据集(PDBBind、BindingDB)含大量带电配体
- espsim 升级到 1.x(如果作者发布)——目前 0.0.1 依赖 setuptools<81,长期维护有风险
9.3 待追踪锚点
- AstexUK/ESP_DNN 的 Issue 区是否有 off-center 元素覆盖更新
- heid-lab/espsim 后续是否升级到支持 hydrogen-only 模式(避免当前必须给完整重原子电荷的限制)
- Linux 服务器迁移到新节点时,PLI 二进制是否仍可直接 exec(依赖 GLIBC 版本)
参考来源
| 资源 | 链接 |
|---|---|
| AstexUK/ESP_DNN | github.com/AstexUK/ESP_DNN |
| heid-lab/espsim | github.com/hesther/espsim |
| Rathi 等J. Med. Chem.2019 | 10.1021/acs.jmedchem.9b01129 |
| Heid & BoecklerJCIM2022 | 10.1021/acs.jcim.1c01535 |
| espsim PyPI | pypi.org/project/espsim |
| TensorFlow 2.15 迁移指南 | tensorflow.org/guide/keras/migrating_to_keras_v2 |
| RDKit release notes | github.com/rdkit/rdkit/releases |
| uv 文档 | docs.astral.sh/uv |
更多专栏:
| 蛋白 / 多肽 | 分子模拟 / 动力学 | 分子对接 / CADD / 工具 | 其他 |
|---|---|---|---|
| 开源蛋白结构推理预测 | 分子模拟基础 | UCSF DOCK系列 | agent智能体系列 |
| 开源蛋白生成方法实践 | 分子动力学模拟-Amber | rDock系列 | 化学大模型介绍(2025) |
| 蛋白药物设计-原理与案例剖析 | 分子动力学模拟-Gromacs | LeDock系列 | 我胡师兄说药 |
| 开源多肽设计模型和方法实践 | 結合自由能 | CADD中的机器学习模型 | siRNA药物设计模型 |
| 开源多肽性质预测 | 高效计算基本配置 | 小分子药物设计-原理与案例剖析 | ASO药物设计模型 |
| 多肽药物设计-原理与案例剖析 | 作用于DNA/RNA的药物设计实践 | 开源小分子生成和设计实践 | 开源药代动力学模拟软件 |