111

NGLView 与 3Dmol.js:网页端三维分子展示方案

在 Notebook 和网页里展示三维分子,NGLView 与 3Dmol.js 是两个主流方案。这篇给出可直接复用的代码。

把三维结构嵌进 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 支持 yellowCarboncyanCarbon 等,比手动指定每个元素方便。

结合 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;这两个工具的价值在交互与嵌入。

延伸资源