mcpField
A
autodock-vina-docking

autodock-vina-docking

github.com/jaechang-hits数据与数据库38486 次安装6 天前更新
代码仓库

关于 autodock-vina-docking

该技能介绍使用 AutoDock Vina 进行 Python 分子对接的流程,涵盖受体与小分子配体准备、构象分析和批量筛选,适用于配体排序及蛋白质-配体结合模式研究。

主要功能

  1. 01准备受体与配体
  2. 02定义对接搜索框
  3. 03使用 Vina 执行对接
  4. 04分析能量与 RMSD
  5. 05可视化对接构象
  6. 06批量筛选化合物库

适用场景

  1. 01预测小分子的结合构象
  2. 02按估算亲和力排列配体
  3. 03针对受体筛选化合物库
  4. 04通过重对接已知配体验证流程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill autodock-vina-docking

安装后在 Claude Code 中输入/autodock-vina-docking确认已加载。

附带文件references/receptor_preparation_guide.mdreferences/scoring_functions_comparison.md

详细介绍

AutoDock Vina 分子对接

概述

AutoDock Vina 是速度最快、应用最广泛的开源分子对接引擎之一,可用于预测蛋白质–配体的结合模式和亲和力。本技能涵盖完整的 Python 流程:从 PDB 准备受体,使用 Meeko 和 RDKit 从 SMILES/SDF 准备配体,定义搜索框,执行对接,分析构象,以及通过批量虚拟筛选识别命中化合物。

适用场景

  • 预测小分子与蛋白质靶标的结合构象
  • 估算相对结合亲和力(kcal/mol),以对配体进行排序
  • 针对靶标受体筛选化合物库
  • 通过重新对接共结晶配体验证对接方案
  • 无需中间文件,直接从 SMILES 字符串准备对接输入
  • 在构效关系研究中比较类似物的结合模式
  • 为分子动力学模拟生成初始构象
  • 如果结合位点未知,盲对接请改用 DiffDock;也可使用 GNINA 作为采用 CNN 评分的替代方案

前置条件

  • Python 包:vina、meeko、rdkit、prody(用于获取 PDB)、py3Dmol(用于可视化)
  • 外部工具:ADFR Suite(提供用于 PDBQT 转换的 prepare_receptor)——从 https://ccsb.scripps.edu/adfr/downloads/ 下载
  • 数据要求:蛋白质结构(PDB 文件或 PDB ID),配体可采用 SMILES、SDF 或 MOL2 格式
  • 环境:建议使用 Python 3.8+、Linux 或 macOS
pip install vina meeko rdkit-pypi prody py3Dmol
# ADFR Suite must be installed separately for prepare_receptor

工作流

步骤 1:获取并准备受体

下载蛋白质结构,移除水分子和杂原子,并转换为 PDBQT 格式。

import prody
import subprocess
from pathlib import Path

# Download PDB structure (example: HIV-1 protease, PDB 1HPV)
pdb_id = "1HPV"
pdb_file = f"{pdb_id}.pdb"
prody.fetchPDB(pdb_id, compressed=False)

# Extract protein chain only (remove water and ligands)
structure = prody.parsePDB(pdb_file)
protein = structure.select("protein")
prody.writePDB(f"{pdb_id}_protein.pdb", protein)
print(f"Protein atoms: {protein.numAtoms()}")

# Convert to PDBQT using ADFR Suite's prepare_receptor
receptor_pdbqt = f"{pdb_id}_receptor.pdbqt"
subprocess.run([
    "prepare_receptor",
    "-r", f"{pdb_id}_protein.pdb",
    "-o", receptor_pdbqt,
    "-A", "hydrogens",  # add hydrogens
], check=True)
print(f"Receptor PDBQT: {receptor_pdbqt}")
步骤 2:确定结合位点

以已知结合位点或共结晶配体为中心,定义对接搜索框。

import numpy as np

# Option A: Center on co-crystallized ligand coordinates
structure = prody.parsePDB(pdb_file)
ligand = structure.select("hetero and not water and not ion")
if ligand is not None:
    center = ligand.getCoords().mean(axis=0)
    # Box size = ligand extent + padding
    extent = ligand.getCoords().max(axis=0) - ligand.getCoords().min(axis=0)
    box_size = extent + 10.0  # 10 Å padding on each side
    print(f"Binding site center: {center}")
    print(f"Box size: {box_size}")
else:
    # Option B: Manual coordinates (from literature or visual inspection)
    center = np.array([15.0, 54.0, 17.0])
    box_size = np.array([25.0, 25.0, 25.0])
    print(f"Using manual box: center={center}, size={box_size}")
步骤 3:从 SMILES 准备配体

使用 RDKit 生成 3D 坐标,并使用 Meeko 转换为 PDBQT 格式。

from rdkit import Chem
from rdkit.Chem import AllChem
from meeko import MoleculePreparation, PDBQTWriterLegacy

# Define ligand (example: Indinavir, HIV protease inhibitor)
smiles = "CC(C)(C)NC(=O)[C@@H]1CN(CCc2ccccc2)C[C@H]1O"
mol_name = "indinavir_analog"

# Generate 3D coordinates with RDKit
mol = Chem.MolFromSmiles(smiles)
mol = Chem.AddHs(mol)
AllChem.EmbedMolecule(mol, randomSeed=42)
AllChem.MMFFOptimizeMolecule(mol)

# Convert to PDBQT using Meeko
preparator = MoleculePreparation()
mol_setups = preparator.prepare(mol)

# Write PDBQT string (for Vina API) or file
pdbqt_string = PDBQTWriterLegacy.write_string(mol_setups[0])[0]
ligand_pdbqt = f"{mol_name}.pdbqt"
with open(ligand_pdbqt, "w") as f:
    f.write(pdbqt_string)
print(f"Ligand PDBQT: {ligand_pdbqt} ({mol.GetNumAtoms()} atoms)")
步骤 4:运行对接

初始化 AutoDock Vina,配置搜索空间并执行对接。

from vina import Vina

# Initialize Vina
v = Vina(sf_name="vina", cpu=4)

# Load receptor and ligand
v.set_receptor(receptor_pdbqt)
v.set_ligand_from_file(ligand_pdbqt)

# Define search space
v.compute_vina_maps(
    center=center.tolist(),
    box_size=box_size.tolist(),
)

# Run docking
v.dock(
    exhaustiveness=32,   # Higher = more thorough (default 8)
    n_poses=10,          # Number of output poses
)

# Write output poses
output_file = f"{mol_name}_docked.pdbqt"
v.write_poses(output_file, n_poses=10, overwrite=True)
print(f"Docking complete. Poses written to {output_file}")
步骤 5:分析对接结果

使用 Vina 内置 API 从对接构象中提取结合能和 RMSD 值。

# Method A: Vina built-in energies (most reliable)
energies = v.energies(n_poses=10)
# Each row: [total, inter, intra, torsions, intra_best_pose]
print(f"{'Pose':<6} {'Total (kcal/mol)':<18} {'Inter':<10} {'Intra':<10}")
print("-" * 44)
for i, e in enumerate(energies):
    print(f"{i+1:<6} {e[0]:<18.2f} {e[1]:<10.2f} {e[2]:<10.2f}")

print(f"\nBest pose: {energies[0][0]:.2f} kcal/mol")

# Method B: Parse PDBQT output with Meeko (for RDKit conversion)
from meeko import PDBQTMolecule, RDKitMolCreate
pdbqt_mol = PDBQTMolecule.from_file(output_file)
best_pose_rdkit = RDKitMolCreate.from_pdbqt_mol(pdbqt_mol)[0]
print(f"Best pose converted to RDKit mol: {best_pose_rdkit.GetNumAtoms()} atoms")
步骤 6:可视化对接结果

使用 py3Dmol 生成对接复合物的 3D 可视化。

import py3Dmol

# Load receptor and best docked pose
with open(f"{pdb_id}_protein.pdb") as f:
    receptor_pdb = f.read()
with open(output_file) as f:
    docked_pdbqt = f.read()

# Create 3D viewer
view = py3Dmol.view(width=800, height=600)
view.addModel(receptor_pdb, "pdb")
view.setStyle({"model": 0}, {"cartoon": {"color": "lightgrey"}})

# Add docked ligand (first model only)
first_model = docked_pdbqt.split("ENDMDL")[0] + "ENDMDL"
view.addModel(first_model, "pdb")
view.setStyle({"model": 1}, {"stick": {"colorscheme": "greenCarbon"}})

# Zoom to ligand
view.zoomTo({"model": 1})
view.show()
# In Jupyter: displays interactive 3D view
# To save: view.png() or view.write_html("docking_result.html")
print("3D visualization rendered")
步骤 7:批量虚拟筛选

使用同一受体筛选化合物库。

import pandas as pd

# Define compound library
compounds = pd.DataFrame({
    "name": ["cpd_001", "cpd_002", "cpd_003", "cpd_004", "cpd_005"],
    "smiles": [
        "CC(=O)Oc1ccccc1C(=O)O",          # Aspirin
        "CC(C)Cc1ccc(cc1)C(C)C(=O)O",      # Ibuprofen
        "OC(=O)c1ccccc1O",                  # Salicylic acid
        "CC12CCC3C(CCC4CC(=O)CCC34C)C1CCC2O",  # Testosterone
        "c1ccc2c(c1)cc1ccc3cccc4ccc2c1c34",     # Pyrene
    ],
})

# Screen all compounds
results = []
for _, row in compounds.iterrows():
    try:
        # Prepare ligand
        mol = Chem.MolFromSmiles(row["smiles"])
        mol = Chem.AddHs(mol)
        AllChem.EmbedMolecule(mol, randomSeed=42)
        AllChem.MMFFOptimizeMolecule(mol)

        mol_setups = preparator.prepare(mol)
        pdbqt_str = PDBQTWriterLegacy.write_string(mol_setups[0])[0]

        # Dock
        v_screen = Vina(sf_name="vina", cpu=2)
        v_screen.set_receptor(receptor_pdbqt)
        v_screen.set_ligand_from_string(pdbqt_str)
        v_screen.compute_vina_maps(center=center.tolist(), box_size=box_size.tolist())
        v_screen.dock(exhaustiveness=16, n_poses=1)

        energy = v_screen.energies(n_poses=1)[0][0]
        results.append({"name": row["name"], "smiles": row["smiles"], "energy_kcal": energy})
        print(f"  {row['name']}: {energy:.2f} kcal/mol")

    except Exception as e:
        results.append({"name": row["name"], "smiles": row["smiles"], "energy_kcal": None})
        print(f"  {row['name']}: FAILED ({e})")

# Rank by binding energy
results_df = pd.DataFrame(results).sort_values("energy_kcal")
results_df.to_csv("screening_results.csv", index=False)
print(f"\nTop hits:\n{results_df.head()}")
步骤 8:保存并导出
import os
os.makedirs("results", exist_ok=True)

# Save summary
results_df.to_csv("results/screening_results.csv", index=False)

# Save best poses for top hits
for _, row in results_df.head(3).iterrows():
    print(f"Top hit: {row['name']} → {row['energy_kcal']:.2f} kcal/mol")

print("Virtual screening complete. Results in results/screening_results.csv")

关键参数

参数默认值范围 / 选项作用
exhaustiveness88-128搜索彻底程度;发表论文时建议设为 32+
n_poses91-20输出的结合构象数量
energy_range3.01.0-5.0纳入的构象与最佳构象之间的最大能量差(kcal/mol)
sf_name"vina""vina"、"ad4"、"vinardo"选择评分函数
cpuall1-N用于对接的 CPU 核心数
box_size (xyz)—每边 15-30 Å搜索空间尺寸;必须涵盖结合位点,并留出 5-10Å 的边缘空间
center (xyz)—结合位点坐标搜索框中心
randomSeed (RDKit)random任意 int生成可复现的 3D 构象
padding (box)10.0 Å5.0-15.0 Å定义搜索框时,在已知配体周围增加的空间

常用方案

方案:重新对接验证(同源配体对接)

适用场景:通过重新对接共结晶配体并检查 RMSD < 2.0 Å 来验证方案。

from rdkit.Chem import AllChem, rdMolAlign

# Extract co-crystallized ligand from PDB
ref_ligand = Chem.MolFromPDBFile(f"{pdb_id}_ligand.pdb", removeHs=False)

# Dock the same ligand
# ... (use steps 3-4 above with the extracted ligand)

# Calculate RMSD between docked pose and crystal structure
rmsd = AllChem.GetBestRMS(ref_ligand, best_pose_rdkit)
print(f"Re-docking RMSD: {rmsd:.2f} Å")
print(f"Validation: {'PASS' if rmsd < 2.0 else 'FAIL'} (threshold: 2.0 Å)")
方案:柔性受体对接

适用场景:结合位点的关键残基需要具有构象自由度(例如,诱导契合)。

# Prepare receptor with flexible sidechains (using ADFR Suite)
# prepare_receptor -r protein.pdb -o rigid.pdbqt -A hydrogens
# prepare_flexreceptor -r rigid.pdbqt -s "A:ARG8,A:ASP25,A:ILE50"

v_flex = Vina(sf_name="vina", cpu=4)
v_flex.set_receptor("rigid.pdbqt", "flex.pdbqt")  # rigid + flexible parts
v_flex.set_ligand_from_file(ligand_pdbqt)
v_flex.compute_vina_maps(center=center.tolist(), box_size=box_size.tolist())
v_flex.dock(exhaustiveness=64, n_poses=10)
v_flex.write_poses("docked_flex.pdbqt", n_poses=5, overwrite=True)
方案:仅评分(不进行对接)

适用场景:无需运行完整搜索,即可评估已预先定位的配体的结合能。

v_score = Vina(sf_name="vina")
v_score.set_receptor(receptor_pdbqt)
v_score.set_ligand_from_file("pre_positioned_ligand.pdbqt")
v_score.compute_vina_maps(center=center.tolist(), box_size=box_size.tolist())

# Score current pose
energy = v_score.score()
print(f"Score: {energy[0]:.2f} kcal/mol")

# Local minimization
energy_min = v_score.optimize()
print(f"After local optimization: {energy_min[0]:.2f} kcal/mol")
v_score.write_pose("minimized.pdbqt", overwrite=True)
方案:比较多种评分函数

适用场景:通过共识评分提高对接结果的可信度。

scoring_results = {}
for sf in ["vina", "vinardo", "ad4"]:
    v_sf = Vina(sf_name=sf, cpu=2)
    v_sf.set_receptor(receptor_pdbqt)
    v_sf.set_ligand_from_file(ligand_pdbqt)
    v_sf.compute_vina_maps(center=center.tolist(), box_size=box_size.tolist())
    v_sf.dock(exhaustiveness=16, n_poses=1)
    scoring_results[sf] = v_sf.energies(n_poses=1)[0][0]

for sf, energy in scoring_results.items():
    print(f"  {sf}: {energy:.2f} kcal/mol")

预期输出

  • {name}_docked.pdbqt — PDBQT 格式的对接构象,头部包含结合能
  • results/screening_results.csv — 虚拟筛选结果:化合物名称、SMILES、结合能(kcal/mol)
  • {pdb_id}_receptor.pdbqt — PDBQT 格式的受体准备文件
  • 图:3D 对接可视化(交互式 py3Dmol 或静态图像)
  • 控制台输出:按排名列出的结合能和每个构象的 RMSD 值

故障排除

问题原因解决方案
找不到 prepare_receptorADFR Suite 不在 PATH 中将 ADFR Suite bin 添加到 $PATH,或使用完整路径
RuntimeError: receptor not set忘记调用 set_receptor对接前调用 v.set_receptor(pdbqt_file)
对接分数非常高(>0)配体在搜索框外或几何结构不佳检查搜索框中心/尺寸是否覆盖结合位点;确认 3D 坐标
所有构象都相同exhaustiveness 过低增至 32-64,以确保可靠采样
Meeko MoleculePreparation 错误输入分子缺少氢原子使用 Meeko 前务必调用 Chem.AddHs(mol)
重对接时 RMSD > 2Å搜索框过小或中心位置错误将搜索框扩大 5Å;确认中心位于共结晶配体处
EmbedMolecule 返回 -1RDKit 未能生成 3D 坐标使用 AllChem.EmbedMolecule(mol, maxAttempts=1000),或尝试 useRandomCoords=True
筛选速度慢(每个化合物 >1 分钟)exhaustiveness 值高且搜索框较大筛选时将 exhaustiveness 降至 8-16;缩小搜索框
找不到 PDBQTWriterLegacyMeeko 版本较旧pip install meeko>=0.5 — API 已从 write_pdbqt_string 更改
多次运行的能量不一致搜索过程不确定在 v.dock(seed=42) 中设置 seed 参数,以确保结果可复现

附带资源

此技能包含用于深入查阅的参考文件。需要时再阅读。

references/receptor_preparation_guide.md

受体准备详细指南:处理缺失残基、质子化状态(依赖 pH)、金属离子、辅因子和多链复合物。提供决策树,说明何时使用 PDB2PQR、PROPKA 或手动质子化。

references/scoring_functions_comparison.md

Vina、Vinardo 和 AD4 评分函数的对比:准确度基准、速度权衡,以及针对不同靶标类别(激酶、蛋白酶、GPCR、核受体)的建议。

参考资料

评论

支持 Markdown