把三维结构嵌进 Jupyter Notebook 或网页,是做交互式分析报告与内部工具的常见需求。NGLView(Python/Notebook 优先)与 3Dmol.js(JavaScript/网页优先)覆盖了这两个场景。
两者的定位
| NGLView | 3Dmol.js | |
|---|---|---|
| 主场景 | Jupyter Notebook | 网页 / 独立 HTML |
| 语言 | Python 封装 | JavaScript(有 py3Dmol 封装) |
| 与 MDAnalysis/MDTraj 集成 | 原生 | 需手动传数据 |
| 轨迹播放 | 支持 | 有限 |
| 体积 | 较大(依赖多) | 轻量(单个 JS 文件) |
| 部署到网页 | 较麻烦 | 简单 |
| 渲染质量 | 好 | 好 |
NGLView:Notebook 中的分子查看器
pip install nglview
# JupyterLab 可能需要:jupyter labextension install nglview-js-widgets
import nglview as nv
# 从文件加载
view = nv.show_file("complex.pdb")
view
# 从 PDB ID 直接加载
view = nv.show_pdbid("4XYZ")
# 从 RDKit 分子
from rdkit import Chem
from rdkit.Chem import AllChem
mol = Chem.AddHs(Chem.MolFromSmiles("CC(=O)Nc1ccc(O)cc1"))
AllChem.EmbedMolecule(mol, randomSeed=0xf00d)
AllChem.MMFFOptimizeMolecule(mol)
view = nv.show_rdkit(mol)
# 自定义显示:结合位点
view = nv.show_file("complex.pdb")
view.clear_representations()
view.add_cartoon(selection="protein", color="lightgrey", opacity=0.5)
view.add_licorice(selection="LIG", color="yellow")
view.add_licorice(selection="protein and (5 of LIG) and sidechainAttached",
color="cyan", radius=0.15)
view.add_ball_and_stick(selection="water and (4 of LIG)", color="red")
view.center("LIG")
view
# 保存图片
view.download_image("binding_site.png", factor=4)
# MD 轨迹
import MDAnalysis as mda
u = mda.Universe("topology.pdb", "trajectory.dcd")
view = nv.show_mdanalysis(u)
view.add_licorice(selection="LIG")
view # 界面上有播放控件
py3Dmol:在 Notebook 中用 3Dmol.js
pip install py3Dmol
import py3Dmol
def show_complex(pdb_path, ligand_resn="LIG", width=800, height=600):
with open(pdb_path) as f:
pdb_data = f.read()
view = py3Dmol.view(width=width, height=height)
view.addModel(pdb_data, "pdb")
# 蛋白:半透明 cartoon
view.setStyle({"cartoon": {"color": "lightgrey", "opacity": 0.6}})
# 配体:棍状,按元素上色
view.addStyle({"resn": ligand_resn},
{"stick": {"colorscheme": "yellowCarbon", "radius": 0.2}})
# 口袋残基侧链
view.addStyle({"within": {"distance": 5, "sel": {"resn": ligand_resn}},
"not": {"atom": ["C", "N", "O"]}},
{"stick": {"colorscheme": "cyanCarbon", "radius": 0.12}})
# 表面(可选)
view.addSurface(py3Dmol.VDW,
{"opacity": 0.25, "color": "white"},
{"within": {"distance": 8, "sel": {"resn": ligand_resn}}})
view.zoomTo({"resn": ligand_resn})
view.setBackgroundColor("white")
return view
show_complex("complex.pdb").show()
# 并排比较多个姿势
view = py3Dmol.view(viewergrid=(1, 2), width=1000, height=400)
view.addModel(open("pose1.pdb").read(), "pdb", viewer=(0, 0))
view.addModel(open("pose2.pdb").read(), "pdb", viewer=(0, 1))
view.setStyle({"stick": {}})
view.zoomTo()
view.show()
嵌入独立网页
<!-- 3Dmol.js 的最简用法:一个 JS 文件搞定 -->
<script src="https://3Dmol.org/build/3Dmol-min.js"></script>
<div id="viewer" style="width:800px;height:600px;position:relative;"></div>
<script>
const viewer = $3Dmol.createViewer("viewer", {backgroundColor: "white"});
// 从 PDB 直接拉取
$3Dmol.download("pdb:4XYZ", viewer, {}, function () {
viewer.setStyle({}, {cartoon: {color: "spectrum", opacity: 0.7}});
viewer.setStyle({hetflag: true, not: {resn: "HOH"}},
{stick: {colorscheme: "yellowCarbon"}});
viewer.zoomTo({hetflag: true});
viewer.render();
});
</script>
<!-- 也可以用 data 属性声明式使用(无需写 JS):
<div class="viewer_3Dmoljs"
data-pdb="4XYZ"
data-backgroundcolor="0xffffff"
data-style="cartoon:color~spectrum"
style="width:800px;height:600px;"></div>
-->
<!-- 注意:
生产环境应把 3Dmol-min.js 下载到本地,
而非依赖 CDN —— 避免外部依赖失效 -->
常见用途
| 场景 | 建议 |
|---|---|
| Notebook 中快速查看结构 | NGLView(一行代码) |
| Notebook 中做定制展示 | py3Dmol(API 更直观) |
| MD 轨迹播放 | NGLView |
| 内部工具/报告网页 | 3Dmol.js |
| 发论文的静态图 | PyMOL(见 110《PyMOL 可视化》) |
| 批量出图 | PyMOL 脚本 |
实用技巧
- Notebook 分享时的坑:NGLView 的输出不会保存在 .ipynb 中——别人打开时是空白。若要分享,用
view.render_image()保存静态图,或改用 py3Dmol(它的 HTML 会内嵌); - 大体系会卡:超过几万个原子时,浏览器渲染会变慢。只加载需要的部分(如结合位点 12 Å 内);
- 表面渲染最耗性能:限制表面只在配体附近生成;
- 轨迹要抽帧:几千帧的轨迹直接加载会占满内存,先降采样;
- 颜色方案:
colorscheme支持yellowCarbon、cyanCarbon等,比手动指定每个元素方便。
结合 Streamlit 做内部工具
# 用 py3Dmol + Streamlit 快速搭一个结构查看工具
import streamlit as st
import py3Dmol
from stmol import showmol # pip install stmol
st.title("对接结果查看器")
uploaded = st.file_uploader("上传复合物 PDB", type=["pdb"])
if uploaded:
pdb_data = uploaded.read().decode()
style = st.selectbox("蛋白显示", ["cartoon", "line", "stick"])
show_surface = st.checkbox("显示表面")
view = py3Dmol.view(width=800, height=600)
view.addModel(pdb_data, "pdb")
view.setStyle({style: {"color": "lightgrey"}})
view.addStyle({"hetflag": True},
{"stick": {"colorscheme": "yellowCarbon"}})
if show_surface:
view.addSurface(py3Dmol.VDW, {"opacity": 0.3})
view.zoomTo({"hetflag": True})
view.setBackgroundColor("white")
showmol(view, height=600, width=800)
# 这类小工具的价值:
# 让不写代码的同事也能查看结果
# → 数十行代码就能显著改善协作效率
关键要点
- NGLView 适合 Notebook 与轨迹播放,3Dmol.js 适合网页部署;
- NGLView 的输出不保存在 .ipynb 中——分享 Notebook 时会变空白;
- 大体系只加载结合位点附近,表面渲染限制范围,轨迹先降采样;
- 发论文的静态图仍应用 PyMOL;这两个工具的价值在交互与嵌入。
延伸资源
- PyMOL:110《PyMOL 可视化》;PLIP 可视化:108《PLIP》;