ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

分子对接与虚拟筛选实战:从原理到自动化流程搭建

2026/9/3 16:40:41 拓冰建站 浏览量
分子对接与虚拟筛选实战:从原理到自动化流程搭建 在药物研发和生物信息学领域分子对接、虚拟筛选和反向钓靶是加速先导化合物发现的核心计算技术。很多同学在学习时常常被繁琐的软件安装、复杂的参数配置和零散的脚本步骤劝退难以形成一个完整的、可复现的工作流。本文将为你系统梳理这三项技术的实战流程从环境搭建、数据准备到批量自动化运行提供一套可直接上手的代码方案。无论你是计算生物学的新手还是希望优化现有流程的开发者都能从中获得一套闭环的解决方案。1. 背景与核心概念在深入操作之前我们有必要厘清这几个关键技术的定义、联系与区别。分子对接是一种预测小分子配体与生物大分子受体如蛋白质之间最佳结合模式和结合亲和力的计算方法。你可以把它想象成一把“钥匙”配体去尝试打开一把“锁”受体计算机会模拟成千上万种插入角度和方式找出最匹配、最稳定能量最低的那一种。其核心原理涉及分子力学、搜索算法和打分函数。虚拟筛选则是分子对接的规模化应用。它并非对接单个分子而是将包含数十万甚至数百万个化合物的分子库逐一与同一个靶点蛋白进行对接计算。通过快速的打分排序从海量化合物中“筛选”出少数可能具有高活性的苗头化合物极大降低了实验筛选的成本和时间。其本质是“批量分子对接排序”。反向钓靶也称为反向对接或靶点垂钓其思路与虚拟筛选相反。它是指将一个已知有生物活性的小分子或药物与一个包含大量蛋白质结构的数据库进行对接。目的是找出这个分子可能作用的潜在生物靶点常用于解释药物作用机制、预测副作用或进行老药新用。核心区别与联系分子对接 vs. 虚拟筛选前者是后者的单次操作单元后者是前者的批量化和自动化应用。虚拟筛选的效率和准确性高度依赖于分子对接的算法和参数。分子对接 vs. 分子动力学分子对接是一种静态或半静态的“快照”预测计算速度快适合大规模筛选但无法模拟结合过程的动态变化。分子动力学则是模拟分子体系随时间推移的运动轨迹能揭示更详细的动态相互作用和构象变化但计算成本极高通常用于对接后对少数顶级复合物进行深入验证和优化。疏水作用距离这是分子对接中一个关键的相互作用力评估参数。疏水作用主要指非极性氨基酸侧链与配体非极性部分之间的排斥水分子、相互聚集的倾向。在打分函数中会评估疏水接触的面积和质量。通常疏水残基与配体疏水基团之间的距离在3.5-5.0 Å范围内被认为是有利的疏水相互作用。设置合理的距离截断值对准确评估结合亲和力至关重要。理解这些概念后我们将从环境准备开始一步步构建自动化流程。2. 环境准备与版本说明一个稳定、可复现的计算环境是成功的第一步。我们选择以AutoDock Vina和RDKit为核心工具因为它们开源、免费、社区支持好且非常适合构建自动化流水线。操作系统本文示例基于 Linux (Ubuntu 20.04/22.04) 或 WSL2 (Windows Subsystem for Linux)。macOS 也可类似操作。编程语言Python 3.8用于编写自动化脚本。核心工具AutoDock Vina (v1.2.3)高性能的分子对接软件。Open Babel (v3.1.1)用于分子格式转换。RDKit (2022.09.5)强大的化学信息学Python库用于处理分子、准备配体。MGLTools (v1.5.7)包含 AutoDockTools用于准备受体和生成对接盒子参数。版本说明不同版本间接口可能略有变化本文代码以常见稳定版本为例。如果你的环境版本不同请关注官方文档的变更说明。2.1 基础环境安装首先更新系统并安装基础编译工具和Python环境。# 更新软件包列表 sudo apt-get update sudo apt-get upgrade -y # 安装编译依赖和Python3 sudo apt-get install -y build-essential cmake python3 python3-pip python3-venv wget git # 验证Python版本 python3 --version pip3 --version2.2 安装核心计算工具1. 安装 AutoDock Vina# 下载预编译版本以Linux x86_64为例 wget https://github.com/ccsb-scripps/AutoDock-Vina/releases/download/v1.2.3/vina_1.2.3_linux_x86_64 # 重命名并赋予可执行权限 mv vina_1.2.3_linux_x86_64 vina chmod x vina # 移动到系统路径或将其路径加入环境变量 sudo mv vina /usr/local/bin/ # 验证安装 vina --help | head -52. 安装 Open Babel# Ubuntu 系统直接安装 sudo apt-get install -y openbabel # 验证安装 obabel -V3. 安装 RDKit推荐使用 conda 安装最为方便。如果使用纯 pip可能遇到编译依赖问题。# 安装 Miniconda (如果未安装) wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda # 初始化conda根据提示操作 $HOME/miniconda/bin/conda init bash # 重新打开终端或 source ~/.bashrc source ~/.bashrc # 创建并激活一个专门的环境 conda create -n drug_design python3.9 rdkit2022.09.5 -c conda-forge -y conda activate drug_design # 验证RDKit安装 python -c import rdkit; print(rdkit.__version__); from rdkit import Chem; print(Chem.MolFromSmiles(CCO))4. 安装 MGLTools (用于准备受体)# 下载MGLTools wget https://ccsb.scripps.edu/mgltools/download/662/mgltools_x86_64Linux2_1.5.7.tar.gz tar -zxvf mgltools_x86_64Linux2_1.5.7.tar.gz cd mgltools_x86_64Linux2_1.5.7 # 运行安装脚本通常选择默认选项 ./install.sh # 安装完成后将bin目录加入PATH例如安装到/home/user下 export PATH$PATH:/home/user/mgltools_x86_64Linux2_1.5.7/bin # 可以将这行export命令添加到~/.bashrc中永久生效安装完成后主要使用其中的prepare_receptor4.py和prepare_ligand4.py脚本。3. 核心原理与自动化流程拆解在动手写代码前我们需要将整个批量流程模块化。一个健壮的自动化流程通常包含以下步骤我们将为每个步骤编写Python函数数据准备模块处理受体和配体文件转换为对接软件所需的格式。对接盒子生成模块定义配体在受体上的结合区域。批量对接执行模块循环调用Vina完成所有配体的对接。结果解析与排序模块提取对接分数筛选最佳结果。反向钓靶适配模块调整流程实现一对多的靶点扫描。3.1 受体与配体准备的关键参数受体准备需要从PDB文件中去除水分子、加氢、计算电荷并分配原子类型最终输出为*.pdbqt格式。prepare_receptor4.py脚本会自动处理这些。配体准备同样需要加氢、计算电荷、分配原子类型并设置可旋转键输出为*.pdbqt格式。对于虚拟筛选我们需要批量处理一个SDF或SMILES列表。对接盒子由中心坐标 (center_x, center_y, center_z) 和盒子尺寸 (size_x, size_y, size_z) 定义。尺寸需要足够大以容纳配体但过大会增加计算时间并降低精度。通常可以基于已知活性配体的坐标或活性位点信息来定义。3.2 虚拟筛选的并行化策略直接串行运行数万次对接是不可接受的。我们将使用Python的multiprocessing库实现多进程并行充分利用多核CPU的计算能力。4. 完整实战案例批量虚拟筛选假设我们有一个靶点蛋白receptor.pdb和一个包含1000个化合物的分子库ligand_library.sdf。我们的目标是在靶点的活性位点进行虚拟筛选。4.1 创建项目结构首先创建一个清晰的项目目录。mkdir virtual_screening_project cd virtual_screening_project mkdir -p data/receptors data/ligands data/output scripts目录说明data/receptors/: 存放受体文件data/ligands/: 存放原始配体库和预处理后的配体data/output/: 存放对接结果scripts/: 存放所有Python脚本4.2 准备受体文件将receptor.pdb放入data/receptors/。使用MGLTools准备受体。# 假设mgltools已在PATH中 prepare_receptor4.py -r data/receptors/receptor.pdb -o data/receptors/receptor.pdbqt -A checkhydrogens -U nphs_lps_waters参数解释-r: 输入受体PDB文件。-o: 输出PDBQT文件。-A checkhydrogens: 检查并添加氢原子。-U nphs_lps_waters: 去除非极性氢、配体和水分子如果存在。4.3 编写自动化脚本在scripts/目录下创建主脚本run_virtual_screen.py。#!/usr/bin/env python3 # -*- coding: utf-8 -*- 虚拟筛选自动化脚本 功能批量准备配体并行运行AutoDock Vina收集结果。 import os import sys import subprocess import multiprocessing as mp from rdkit import Chem from rdkit.Chem import AllChem import pandas as pd import logging from typing import List, Tuple # 配置日志 logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) # 定义路径 (请根据实际情况修改) BASE_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__))) RECEPTOR_PDBQT os.path.join(BASE_DIR, data/receptors/receptor.pdbqt) LIGAND_LIB_SDF os.path.join(BASE_DIR, data/ligands/ligand_library.sdf) OUTPUT_DIR os.path.join(BASE_DIR, data/output) PREPARED_LIG_DIR os.path.join(BASE_DIR, data/ligands/prepared) VINA_PATH /usr/local/bin/vina # 你的Vina路径 PREPARE_LIGAND_SCRIPT /home/user/mgltools_x86_64Linux2_1.5.7/bin/prepare_ligand4.py # 你的prepare_ligand4.py路径 # 对接盒子参数 (需要根据你的受体活性位点调整) BOX_CENTER [15.0, 12.5, 10.0] # x, y, z BOX_SIZE [20.0, 20.0, 20.0] # x, y, z EXHAUSTIVENESS 8 # Vina搜索强度值越大越彻底耗时越长 NUM_MODES 5 # 每个对接保存的构象数 def prepare_single_ligand(smi: str, mol_id: str) - str: 使用RDKit将SMILES转换为3D构象并生成PDBQT文件。 参数: smi: 配体的SMILES字符串 mol_id: 分子标识符 返回: 生成的PDBQT文件路径 try: mol Chem.MolFromSmiles(smi) if mol is None: logger.warning(f无法解析SMILES: {smi}) return None mol Chem.AddHs(mol) # 加氢 # 生成3D坐标 AllChem.EmbedMolecule(mol, AllChem.ETKDG()) # 能量最小化 AllChem.MMFFOptimizeMolecule(mol) # 保存为临时mol2文件因为prepare_ligand4.py接受mol2格式 temp_mol2 os.path.join(PREPARED_LIG_DIR, f{mol_id}_temp.mol2) temp_pdbqt os.path.join(PREPARED_LIG_DIR, f{mol_id}.pdbqt) Chem.MolToMolFile(mol, temp_mol2) # 调用MGLTools脚本准备配体 cmd [python2, PREPARE_LIGAND_SCRIPT, -l, temp_mol2, -o, temp_pdbqt] result subprocess.run(cmd, capture_outputTrue, textTrue) if result.returncode ! 0: logger.error(f准备配体 {mol_id} 失败: {result.stderr}) return None # 清理临时文件 os.remove(temp_mol2) logger.info(f配体 {mol_id} 准备完成.) return temp_pdbqt except Exception as e: logger.error(f处理配体 {mol_id} 时发生异常: {e}) return None def run_vina_docking(ligand_pdbqt: str, output_prefix: str) - List[Tuple[float, str]]: 运行单次Vina对接。 参数: ligand_pdbqt: 配体PDBQT文件路径 output_prefix: 输出文件前缀 返回: 一个列表包含(打分, 输出文件路径)元组 output_pdbqt os.path.join(OUTPUT_DIR, f{output_prefix}_out.pdbqt) log_file os.path.join(OUTPUT_DIR, f{output_prefix}_log.txt) vina_cmd [ VINA_PATH, --receptor, RECEPTOR_PDBQT, --ligand, ligand_pdbqt, --center_x, str(BOX_CENTER[0]), --center_y, str(BOX_CENTER[1]), --center_z, str(BOX_CENTER[2]), --size_x, str(BOX_SIZE[0]), --size_y, str(BOX_SIZE[1]), --size_z, str(BOX_SIZE[2]), --exhaustiveness, str(EXHAUSTIVENESS), --num_modes, str(NUM_MODES), --out, output_pdbqt ] try: with open(log_file, w) as logf: result subprocess.run(vina_cmd, stdoutlogf, stderrsubprocess.PIPE, textTrue, checkTrue) # 解析输出日志提取对接打分 scores [] with open(log_file, r) as f: lines f.readlines() for line in lines: if RESULT: in line: parts line.strip().split() # 格式: RESULT: 打分值 if len(parts) 2: try: score float(parts[1]) scores.append((score, output_pdbqt)) except ValueError: continue logger.info(f对接完成: {output_prefix}, 最佳打分: {scores[0][0] if scores else N/A}) return scores except subprocess.CalledProcessError as e: logger.error(fVina对接失败 {output_prefix}: {e.stderr}) return [] def process_ligand(args): 供多进程调用的包装函数处理一个配体。 idx, smi, mol_id args # 1. 准备配体 lig_file prepare_single_ligand(smi, mol_id) if not lig_file: return None # 2. 运行对接 output_prefix fligand_{idx:04d}_{mol_id} scores run_vina_docking(lig_file, output_prefix) # 3. 返回结果 (最佳打分, 分子ID) best_score scores[0][0] if scores else 999.0 # 999表示失败 return (best_score, mol_id, output_prefix) def main(): 主函数 # 创建必要的目录 os.makedirs(PREPARED_LIG_DIR, exist_okTrue) os.makedirs(OUTPUT_DIR, exist_okTrue) # 步骤1: 读取配体库 (这里以SDF为例) logger.info(正在读取配体库...) supplier Chem.SDMolSupplier(LIGAND_LIB_SDF, removeHsFalse) ligand_data [] for i, mol in enumerate(supplier): if mol is None: continue # 尝试从SDF属性中获取ID否则使用索引 mol_id mol.GetProp(_Name) if mol.HasProp(_Name) else fMol_{i} smi Chem.MolToSmiles(mol) ligand_data.append((i, smi, mol_id)) logger.info(f共读取到 {len(ligand_data)} 个有效配体.) # 步骤2: 多进程并行处理 logger.info(开始并行虚拟筛选...) num_cpus max(1, mp.cpu_count() - 1) # 留一个核心给系统 with mp.Pool(processesnum_cpus) as pool: results pool.map(process_ligand, ligand_data) # 步骤3: 收集并分析结果 logger.info(筛选完成正在汇总结果...) valid_results [r for r in results if r is not None] # 按打分排序 (Vina打分为负值越小越好) sorted_results sorted(valid_results, keylambda x: x[0]) # 保存结果到CSV df pd.DataFrame(sorted_results, columns[Best_Score, Ligand_ID, Output_Prefix]) result_csv os.path.join(OUTPUT_DIR, virtual_screening_results.csv) df.to_csv(result_csv, indexFalse) logger.info(f结果已保存至: {result_csv}) # 打印Top 10 print(\n 虚拟筛选 Top 10 结果 ) print(df.head(10).to_string(indexFalse)) if __name__ __main__: main()4.4 运行与验证放置数据确保receptor.pdb和ligand_library.sdf在正确的data/子目录下。修改脚本路径根据你的实际安装路径修改脚本中VINA_PATH和PREPARE_LIGAND_SCRIPT变量。调整盒子参数这是关键你需要确定活性位点的坐标。可以使用PyMOL、ChimeraX等可视化软件打开receptor.pdb找到活性口袋查看其中心坐标。将BOX_CENTER和BOX_SIZE替换为你的值。运行脚本cd virtual_screening_project conda activate drug_design # 激活RDKit环境 python scripts/run_virtual_screen.py监控输出脚本会实时打印日志显示配体准备和对接进度。最终会在data/output/下生成每个配体的对接结果文件 (*_out.pdbqt) 和一个汇总的CSV文件virtual_screening_results.csv。4.5 结果说明virtual_screening_results.csv文件包含所有成功对接配体的信息按最佳对接打分结合亲和力单位通常是 kcal/mol升序排列。分数越负表示预测的结合能力越强。你可以用PyMOL等软件打开打分靠前的配体输出文件 (*_out.pdbqt)将其与受体 (receptor.pdbqt) 一起加载可视化分析预测的结合模式、氢键、疏水相互作用等。5. 常见问题与排查思路在运行批量流程时你可能会遇到以下典型问题问题现象常见原因解决思路prepare_receptor4.py执行失败1. MGLTools未正确安装或PATH未设置。2. 受体PDB文件格式不规范如缺失原子。1. 检查脚本路径确保使用python2调用。2. 使用PDB修复工具或服务器在线处理PDB文件。RDKit无法解析SMILES或生成3D坐标1. SMILES字符串无效。2. 分子过于复杂或含有RDKit不支持的原子类型。1. 使用Chem.MolFromSmiles(smi, sanitizeFalse)尝试解析或检查原始数据。2. 考虑使用其他工具如Open Babel进行初步转换。Vina对接失败输出空文件或报错1. 盒子中心或尺寸设置错误盒子不在蛋白内或过大过小。2. 配体PDBQT文件格式错误如电荷、原子类型。3. 受体和配体使用了不兼容的力场参数。1.仔细检查并调整盒子参数这是最常见原因。先用一个已知活性配体测试。2. 用文本编辑器检查生成的PDBQT文件确保配体原子和电荷完整。3. 确保受体和配体都是用MGLTools的同一套流程准备的。并行进程卡死或内存溢出1. 单个对接任务内存需求大并行数过多。2. 脚本中存在文件读写冲突。1. 减少mp.Pool的进程数 (processes)。2. 确保每个进程写入独立的输出文件避免竞争。对接打分全部很差正值或很小的负值1. 盒子未覆盖真正的结合位点。2. 配体库本身与靶点不匹配。3. 受体准备时活性位点关键残基如辅因子、金属离子被去除。1. 重新分析活性位点调整盒子。2. 检查配体库的类药性。3. 在准备受体时使用-U参数谨慎选择去除的对象必要时保留关键水分子或离子。通用排查步骤简化测试先用一个已知的活性配体如果有和受体进行单次对接测试确保基础流程畅通。检查日志仔细阅读Vina和准备脚本生成的日志文件 (*_log.txt)里面常有错误提示。可视化验证用PyMOL等软件加载受体和盒子可以用脚本生成一个显示盒子大小的伪分子确保盒子位置正确。逐步执行注释掉并行部分先测试单个配体的完整流程准备-对接-解析再扩展到批量。6. 反向钓靶流程适配与最佳实践反向钓靶的流程与虚拟筛选高度相似只是将“一个受体 vs. 多配体”变为“一个配体 vs. 多受体”。基于上面的脚本我们可以快速改造。6.1 流程改造要点输入一个配体已知药物分子的初始文件如.sdf,.mol2一个包含多个蛋白质结构的受体数据库目录。循环主体外层循环遍历每个受体文件内层调用相同的配体准备和对接函数。输出对每个受体记录与该配体的最佳对接打分最后对所有受体进行排序打分最好的受体即为潜在的靶点。6.2 关键脚本修改示例假设受体数据库在data/receptor_db/目录下均为.pdb格式。# 在原有脚本基础上增加反向钓靶函数 def run_reverse_screening(ligand_smiles: str, ligand_id: str, receptor_db_dir: str): 运行反向钓靶 # 1. 准备查询配体 query_ligand_pdbqt prepare_single_ligand(ligand_smiles, ligand_id) if not query_ligand_pdbqt: logger.error(查询配体准备失败退出。) return results [] receptor_files [f for f in os.listdir(receptor_db_dir) if f.endswith(.pdb)] logger.info(f开始在 {len(receptor_files)} 个受体中进行反向钓靶...) for rec_file in receptor_files: rec_name os.path.splitext(rec_file)[0] rec_path os.path.join(receptor_db_dir, rec_file) rec_pdbqt_path os.path.join(receptor_db_dir, f{rec_name}.pdbqt) output_prefix f{ligand_id}_vs_{rec_name} # 2. 准备当前受体 prep_cmd [python2, PREPARE_RECEPTOR_SCRIPT, -r, rec_path, -o, rec_pdbqt_path] subprocess.run(prep_cmd, capture_outputTrue) # 简化处理生产环境需加错误检查 # 3. 运行对接 (可复用之前的run_vina_docking但需传入不同的受体路径) # 这里需要稍微修改run_vina_docking函数以接受受体路径参数为简洁起见我们直接内联核心命令 vina_cmd [ VINA_PATH, --receptor, rec_pdbqt_path, --ligand, query_ligand_pdbqt, --center_x, str(BOX_CENTER[0]), # 注意反向钓靶时盒子需要针对每个受体定义或使用全局盲对接盒子 --center_y, str(BOX_CENTER[1]), --center_z, str(BOX_CENTER[2]), --size_x, str(BOX_SIZE[0]), --size_y, str(BOX_SIZE[1]), --size_z, str(BOX_SIZE[2]), --exhaustiveness, str(EXHAUSTIVENESS), --num_modes, str(NUM_MODES), --out, os.path.join(OUTPUT_DIR, f{output_prefix}_out.pdbqt) ] # ... 执行命令并解析打分 ... # best_score 解析出的最佳打分 # results.append((best_score, rec_name, output_prefix)) # 4. 排序并输出结果 # ... 同虚拟筛选 ...反向钓靶的特殊性盒子定义由于你不知道配体在每个受体上的结合位点通常采用“盲对接”策略即定义一个覆盖整个受体或大部分区域的超大盒子或者使用基于受体结构的活性位点预测工具来定义多个可能盒子。受体数据库质量数据库中的蛋白结构需要经过预处理去水、加氢、补全缺失残基等且结构分辨率越高越好。计算量对接一个配体到成千上万个受体上计算量巨大必须依赖高性能计算集群或云服务器进行大规模并行。6.3 工程实践与优化建议配置管理将盒子参数、路径、Vina参数等写入一个独立的配置文件如config.yaml使脚本更易维护和移植。日志与监控为每个对接任务生成详细的日志并记录开始/结束时间、资源消耗便于排查故障和性能分析。断点续跑在脚本中记录处理进度如果程序意外中断可以从断点处继续避免重复计算。结果去重虚拟筛选结果中结构相似的分子可能打分相近。可以使用RDKit的分子指纹如Morgan指纹和相似性计算Tanimoto系数对Top结果进行聚类选择代表性分子。性能优化并行粒度对于虚拟筛选以配体为并行单元效率高。对于反向钓靶以受体为并行单元。I/O优化将配体准备步骤提前批量完成避免在每次对接时重复进行格式转换。使用更快的对接工具对于超大规模筛选可以考虑使用smina(Vina的优化版) 或QuickVina 2等提速工具。验证与评估对于虚拟筛选如果有已知的活性化合物和阴性化合物可以计算富集因子(EF)和ROC曲线来评估筛选流程的有效性。对于反向钓靶需要通过文献或实验数据对预测的潜在靶点进行验证。通过将核心流程模块化、参数化并辅以健壮的错误处理和日志记录你就可以构建一个适应不同项目需求的、可靠的批量分子对接计算平台。这套流程不仅是学习工具稍加改造即可用于实际的科研或早期药物发现项目。