BioEmu2 是微软 Microsoft Research AI for Science 发布的全原子生物分子结构与动力学模型,代码和预览版权重已公开。输入蛋白、核酸、小分子等组分,它可以生成结构、采样多种构象,也可以从一个已有构象出发,预测一段时间后的结构。
本文在 Linux + conda + NVIDIA RTX 4080 SUPER 上实测了两个体系:腺苷酸激酶 ADK 和 肌红蛋白。每个体系先生成 8 个初始候选,选一个作为起点,再推进 4 条轨迹:每条推进 20 次、每次 50 ns,加上起点共 21 帧,覆盖 1 μs 模型时间。下文依次介绍安装、YAML 输入、MSA、运行参数,以及多轨迹动画和接触热图的制作与解读。
code :https://github.com/microsoft/bioemu2
1 认识 BioEmu2
1.1 能做什么
一句话概括:输入分子组成,输出三维结构,并给出它可能怎样运动。
输入可以是蛋白、核酸、小分子等,支持单个分子和多链复合物;蛋白还可以额外提供 MSA 和接触信息。输出是全原子坐标,可用来查看折叠、结构域运动、结合口袋和分子间接触。
研究中我们通常关心三件事:结构长什么样、哪些部位会动、加入另一条链或配体后有没有变化。BioEmu2 把结构预测、多构象采样和时间推进放进了同一个模型。本文的 ADK 案例观察结构域和残基接触的变化,肌红蛋白案例观察血红素口袋和配体接触。
1.2 工作原理
BioEmu2 是约 5 亿参数的全原子扩散模型。训练数据包括 PDB 实验结构、AFDB 等预测结构,以及微软生成的分子动力学轨迹。前两类数据让模型学会"结构长什么样",轨迹数据让模型学会"结构怎么变"。
生成一个结构大致分三步:
时间推进的思路很直接:给定当前构象和时间间隔,模型采样"这段时间之后可能的构象"。每次调用只返回一个未来构象;把它作为下一次的起点反复调用,就串成一条轨迹。同一起点配合不同的随机噪声,就能得到多条轨迹。
模型不会输出这 50 ns 内的中间过程。
1.3 主要功能
|
|
|
|
|---|---|---|
|
|
|
bioemu2 predict-structure
|
|
|
|
bioemu2 sample-equilibrium
|
|
|
|
bioemu2 propagate
EmuSession.propagate();官方建议间隔取训练覆盖的 1–1000 ns
|
|
|
|
|
使用方式:BioEmu2 先根据给定序列生成结构,再从初始结构出发,采样一段时间后可能的构象。按本文设置,每次推进 50 ns,反复执行,直到达到设定时间。
1.4 本文流程
两个案例走同一套流程:
定义分子组成 → 准备 MSA → 生成并筛选初始候选 → 从同一起点推进 4 条轨迹 → 分析接触、制作动画
每条轨迹 21 帧,覆盖 1 μs。第 6 节提供一个分析 skill,装进 agent 后可以直接处理这些结果。
2 安装
2.1 环境与目录
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
软件、权重和缓存放在 ~/program/bioemu2,输入和结果放在 ~/work/bioemu2_tutorial_20261103,推理使用独立的 bioemu2 conda 环境。
# 创建软件与任务目录
mkdir -p ~/program/bioemu2
mkdir -p ~/work/bioemu2_tutorial_20261103/{inputs/msa,results,analysis}
2.2 创建 conda 环境
仓库支持 Python 3.12–3.14,官方基准和本文都用 3.12。uv 用来安装 Python 依赖。
# 创建并激活独立环境
source ~/miniconda3/etc/profile.d/conda.sh
conda create -n bioemu2 -c conda-forge python=3.12 pip uv -y
conda activate bioemu2
2.3 下载源码并安装依赖
源码固定到本次使用的 commit,确保输入格式和默认参数与实测一致。RTX 4080 SUPER 的计算能力为 8.9,满足官方 cuda 扩展的要求。
# 下载源码并切换到本次实测版本
git clone https://github.com/microsoft/bioemu2.git ~/program/bioemu2/bioemu2
cd ~/program/bioemu2/bioemu2
git checkout 06be369dd555849165a737472d42d936959e46fc
# 安装 CUDA 扩展和作图依赖
export UV_CACHE_DIR=~/program/bioemu2/cache/uv
uv pip install -e '.[cuda]' matplotlib pillow
3 权重与运行资源
本文使用 bioemu2-preview,Hugging Face revision 固定为 dd4b0c1b69984b68edcb6200a544213be4d75242。
先在终端中设置缓存目录。后面的 Python 代码按顺序放在同一个 Python 会话或 Notebook 中执行。
# 激活环境并设置缓存目录
conda activate bioemu2
export HF_HOME=~/program/bioemu2/cache/huggingface
export HF_HUB_CACHE=~/program/bioemu2/cache/huggingface/hub
export BIOEMU2_MSA_CACHE=~/program/bioemu2/cache/msa
export BIOEMU2_CCD_CACHE=~/program/bioemu2/cache/ccd
export BIOEMU2_TEMPLATE_CACHE=~/program/bioemu2/cache/templates
export BIOEMU2_EMBEDS_CACHE=~/program/bioemu2/cache/embeddings
模型支持首次加载时自动下载权重。
from pathlib import Path
from huggingface_hub import snapshot_download
model_dir = snapshot_download(
repo_id="microsoft/bioemu2",
revision="dd4b0c1b69984b68edcb6200a544213be4d75242",
allow_patterns="checkpoints/bioemu2-preview/*",
)
checkpoint = Path(model_dir) / "checkpoints/bioemu2-preview/checkpoint.ckpt"
官方源连接不稳定时,可在启动 Python 前设置镜像:
export HF_ENDPOINT=https://hf-mirror.com
MSA 来自公共 ColabFold 服务,HEM、NBN、SO4 等化学组分定义由程序按需下载并缓存,不需要在服务器上部署完整数据库。
4 输入准备与关键参数
4.1 两个体系
ADK 直接使用官方的 ake.yaml:一条 214 aa 的蛋白链,不含配体。肌红蛋白以官方 myoglobin_101m.yaml 为基础,包含 154 aa 蛋白、SO4、HEM 和 NBN。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
补充说明:
references/ 中的实验 CIF 只用于核对输入;轨迹起点由模型采样得到。
4.2 YAML 输入
entities 列出各个组分:蛋白写完整序列,配体写 CCD 编码,asym_ids 指定链名。在 ~/work/bioemu2_tutorial_20261103 目录下,将下面两份配置分别保存为 inputs/adk.yaml 和 inputs/myoglobin.yaml,后面的代码直接读取它们。
ADK:inputs/adk.yaml
# E. coli adenylate kinase (AKE, PDB 4AKE) System.
entities:
- entity_type: protein
asym_ids:
- A
sequence: MRIILLGAPGAGKGTQAQFIMEKYGIPQISTGDMLRAAVKSGSELGKQAKDIMDAGKLVTDELVIALVKERIAQEDCRNGFLLDGFPRTIPQADAMKEAGINVDYVLEFDVPDELIVDRIVGRRVHAPSGRVYHVKFNPPKVEGKDDVTGEELTTRKDDQEETVRKRLVEYHQMTAPLIGYYSKEAEAGNTKYAKVDGTKPVAEVRADLEKILG
mods: []
bonds: []
肌红蛋白:inputs/myoglobin.yaml
# 101M composition; no extra contact conditioning.
entities:
- entity_type: protein
sequence: MVLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRVKHLKTEAEMKASEDLKKHGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHPGNFGADAQGAMNKALELFRKDIAAKYKELGYQG
asym_ids: A
- entity_type: ligand
ccd_code: SO4
asym_ids: B
- entity_type: ligand
ccd_code: HEM
asym_ids: C
- entity_type: ligand
ccd_code: NBN
asym_ids: D
|
|
|
|---|---|
entity_type |
protein 和 ligand
|
sequence |
|
asym_ids |
|
ccd_code |
|
mods
bonds
|
|
肌红蛋白输入没有加 contacts,也没有声明额外的共价键或金属配位键。
4.3 准备 MSA
BioEmu2 默认从公共 ColabFold 服务获取 MSA。下面依次处理两个蛋白:已有 A3M 时直接读取,没有时查询公共服务,然后保存到 inputs/msa/。
# 获取MSA
from bioemu2 import get_msa, load_system_and_contacts
task = Path.home() / "work/bioemu2_tutorial_20261103"
for case in ("adk", "myoglobin"):
system, _ = load_system_and_contacts(task / "inputs" / f"{case}.yaml")
msa_path = task / "inputs/msa" / f"{case}.a3m"
msa = get_msa(system, source=msa_path) if msa_path.exists() else get_msa(system)
msa_path.write_text(msa.a3m())
print(case, "A3M records:", len(msa))
两个体系都只有一条蛋白链,不涉及 paired MSA。MSA 深度如下;当前版本的预处理默认最多使用前 4,092 行。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
4.4 关键参数
先分清几组概念:
四条轨迹从同一个起点出发,之后各自使用不同的随机噪声。
|
|
|
|
|---|---|---|
num_starts |
|
|
num_trajectories |
|
|
num_steps |
|
|
lag_time_ns |
|
|
batch_size |
|
|
seed |
|
|
|
|
edm
|
|
起点怎么选:
high_quality 检查蛋白几何;
5 实际运行
两例共用下面这段代码,按顺序完成读取输入 → 生成候选 → 选择起点 → 连续推进 → 保存轨迹。准备好前面的 YAML、MSA 和 checkpoint 后,在同一个 Python 会话中继续执行。
# 示例代码
import mdtraj as md
import numpy as np
from bioemu2 import (
EmuSession, check_physicality, join_trajectory_steps,
load_model, save_frames,
)
num_starts = 8
num_trajectories = 4
num_steps = 20
lag_time_ns = 50
batch_size = 4
model = load_model(checkpoint_path=checkpoint)
for case, seed in [("adk", 20261103), ("myoglobin", 20261104)]:
system, contacts = load_system_and_contacts(task / "inputs" / f"{case}.yaml")
msa = get_msa(system, source=task / "inputs/msa" / f"{case}.a3m")
emu = EmuSession(system, model=model, mode="equilibrium", msa=msa, contacts=contacts)
out = task / "results" / case
# 生成初始候选,保留必要的蛋白几何筛选
candidates = emu.sample(num_samples=num_starts, batch_size=batch_size, seed=seed)
report = check_physicality(candidates, system=system)
save_frames(candidates, out / "starting_candidates", physicality=report)
eligible = report.passed.copy()
# 肌红蛋白额外筛选 His94 NE2–HEM FE 距离,MDTraj 的 nm 转为 Å
if case == "myoglobin":
his = next(a.index for a in system.topology.atoms
if a.residue.chain.chain_id == "A"
and a.residue.resSeq == 94 and a.name == "NE2")
fe = next(a.index for a in system.topology.atoms
if a.residue.chain.chain_id == "C" and a.name == "FE")
distance = md.compute_distances(candidates, [[his, fe]], periodic=False)[:, 0] * 10
eligible &= (distance >= 1.5) & (distance <= 3.0)
selected = int(np.flatnonzero(eligible)[0])
print(case, "起点候选:", selected + 1)
step_frames = [candidates[[selected] * num_trajectories]]
# 每次同时推进四条轨迹;本次输出作为下一次输入
for step in range(1, num_steps + 1):
frames = emu.propagate(
step_frames[-1],
lag_time_ns=lag_time_ns,
batch_size=batch_size,
seed=seed + 1000 + step,
)
step_frames.append(frames)
# 将按步骤排列的构象整理为四条轨迹;时间自动设为 ps
trajectories = join_trajectory_steps(step_frames, lag_time_ns=lag_time_ns)
for i, trajectory in enumerate(trajectories, 1):
report = check_physicality(trajectory, system=system)
folder = out / f"trajectory_{i:02d}"
save_frames(trajectory, folder, physicality=report)
np.savez_compressed(folder / "coordinates.npz", xyz=trajectory.xyz, time=trajectory.time)
step_frames 中每一项都包含四条轨迹在同一步的构象;join_trajectory_steps() 将它们拆成四条时间有序的轨迹,并设置 0、50、100……1000 ns 对应的时间。physicality.json 记录每帧的几何检查结果,全部推进帧都会保存。
配套材料中已经包含完整的 results/。直接分析可进入第 6 节;自己重新计算时,先按第 7.3 节保留已有结果。
5.1 ADK:四条轨迹与残基接触
ADK 使用随机种子 20261103,选择第一个通过蛋白几何筛选的候选作为四条轨迹的共同起点。
结果:8 个初始候选都通过了几何检查,选第 1 个作为起点。4 条轨迹都推进到 1 μs,80 个推进端点全部通过 high_quality 检查。
图 1|ADK 多轨迹动画。灰色为 CORE,紫色为 NMP(30–59),金色为 LID(122–159),四条轨迹都按 CORE 对齐。21 个原始帧经插值扩展为 201 帧,以 25 fps 播放,Display t 标出插值位置。可以看到 NMP、LID 和环区在各条轨迹中的位置变化,整体折叠保持稳定。
图 2|ADK 残基接触。左图统计 50–500 ns,中图统计 550–1000 ns,右图为两者之差(后减前)。占有率范围 0–1,差值色阶 −0.4–0.4;细线标出 CORE、NMP、LID 的边界,灰色格子是被排除的自身和相邻残基。
下表列出两组变化最大的接触,以及一组 CORE/NMP 边界附近的接触(编号对应输入序列):
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这说明在本次轨迹中,部分局部接触发生了调整。完整数据和每条轨迹单独计算的差值在 analysis/adk/ 中,可以进一步检查某个变化是否在多条轨迹中方向一致。
5.2 肌红蛋白:四条轨迹与配体接触
肌红蛋白由上面的循环接着计算,使用随机种子 20261104,推进参数与 ADK 相同。起点额外要求 His94 NE2–FE 距离位于 1.5–3.0 Å;这一筛选只影响起点选择,不会在推进过程中添加配位键或约束。
结果:8 个初始候选都通过了几何检查,His94 NE2–FE 距离也都在 1.5–3.0 Å 内。选第 1 个候选为起点,距离为 2.44 Å;80 个推进端点全部通过几何检查。
图 3|肌红蛋白多轨迹动画。蛋白为灰色半透明 cartoon,HEM 为紫色,NBN 为金色,SO4 为青色。四条轨迹按蛋白 Cα 对齐,使用相同的视角和缩放,便于比较口袋和配体的相对位置。动画同样是 201 帧、25 fps 的插值展示;热图只使用原始帧。
图 4|肌红蛋白配体–残基接触。每个面板从上到下依次为 HEM、NBN、SO4,横轴为蛋白残基编号。前两个面板是占有率(0–1),差值面板为 −0.3–0.3。SO4 的接触比较分散,HEM 和 NBN 集中在口袋附近。
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
另外,HEM–His94 和 NBN–His65 在两个时间窗口中都是 100% 接触。按原子距离复核,80 个推进端点的 His94 NE2–FE 距离为 1.97–2.43 Å,中位数 2.18 Å。这些结果只描述本次轨迹中的口袋几何和接触情况,没有用来计算解离速率或结合自由能。
6 用 skill 制作动画和接触热图
我们把分析流程打包成了 bioemu2-analysis skill。把它放进支持 SKILL.md 的 agent 技能目录后,完成运行后直接给 agent 指明结果在哪、要分析什么,它就会调用附带的脚本完成接触分析、轨迹对齐和动画制作。
6.1 skill 内容
下载 BioEmu2 分析 skill:
网盘链接: https://pan.baidu.com/s/1z0MFl5_rlH1g0ZRqq6c7Hw?pwd=4jah
提取码: 4jah
bioemu2-analysis/
SKILL.md # agent 的使用说明与统计约定
agents/openai.yaml # 显示名称与默认调用提示
scripts/
analyze.py # 读取坐标、接触统计、热图和对齐
render_chimerax.py # 统一视角与平滑过渡帧
compose_animation.py # 并排 GIF/MP4
requirements.txt # 分析与合成所需依赖
references/
data-contract.md # 输入、单位、JSON 配置和输出定义
workflow.md # 命令、依赖与核验方法
assets/
adk.json # 本文 ADK 的配置
myoglobin.json # 本文肌红蛋白的配置
输入为同一次输出中的 topology.cif 和 samples.xtc,也支持本文保存的 coordinates.npz。轨迹条数和帧数不限,但并排展示的轨迹必须原子组成、顺序和帧数一致,时间轨迹的时间点也要一致。处理新体系时,修改链、配体、对齐区域、接触阈值和时间窗口即可,不要照搬 ADK 的结构域编号。
6.2 安装与使用
直接将压缩包发给 agent 然后说安装这个 skill。
处理自己的体系时,换成实际路径,让 agent 根据拓扑生成 JSON 配置。
对齐方式可以参考本文:ADK 按 CORE 的 Cα 对齐,以保留 NMP、LID 的相对运动;肌红蛋白按蛋白 Cα 对齐。
其他蛋白默认按全部蛋白 Cα 对齐,也可以指定一个稳定的结构域。
7 输出、耗时与重新运行
7.1 结果目录
XTC 用于常见的分子可视化软件;NPZ 保留浮点坐标,供接触统计读取。
results/adk/ # myoglobin 使用相同结构
starting_candidates/
topology.cif # 第一个初始候选
samples.xtc # 全部 8 个初始候选
physicality.json # 初始候选的几何检查
trajectory_01/ … trajectory_04/
topology.cif # 拓扑和第一帧坐标
samples.xtc # 21 帧时间有序轨迹
coordinates.npz # xyz 为 nm,time 为 ps
physicality.json # 每个原始帧的几何检查
topology.cif 只含第一帧坐标,读取完整轨迹要同时加载 samples.xtc。每例共 4×21=84 帧,其中 4 个 t=0 是同一个起点,真正新增的推进端点是 80 个,热图基于这 80 帧。
7.2 耗时与显存
本机实测,batch_size=4。每次推进同时生成四条轨迹的下一帧。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

