Autodock vina自动化运行
autodock vina 现在还是比较常用了,虽说config file之类的还是比较直观易懂的,但是一般来说我们做一个东西都要同时dock很多个ligand。下面就是我常用的autodock vina自动化运行脚本。
- 自动化批量对接(Batch Docking): 自动扫描指定目录下的所有配体文件(
.pdbqt),并逐个与受体(Receptor)进行对接。 - 智能参数记忆(State Persistence): 首次输入参数后,脚本会自动将其缓存到隐藏文件
.dockenv中。下次运行时直接回车即可跳过输入,极大提升复用效率。 - 动态生成配置与日志(Auto-Logging): 自动为每个配体生成专属的
config.txt配置文件,并实时保存带有时间戳的详细运行日志(.out)。 - 重名防覆盖保护(File Protection): 如果输出目录已存在同名对接结果,脚本会自动给新文件加上序号(如
_1,_2),防止实验数据被意外覆盖。
用户输入内容:
| 序号 | 允许用户输入的内容 (Input) | 默认值 (Default) | 说明 (Notes) |
| 1 | Receptor 文件路径 (受体蛋白质文件) | 优先使用上次成功运行的受体; 若无历史记录则无默认值,需手动输入。 | 脚本会自动检查该文件是否存在,不存在会提示重新输入。 |
| 2 | Ligand 配体目录路径 (存放小分子的文件夹) | 优先使用上次的目录; 无历史记录时默认为当前目录 ( | 脚本会自动扫描该目录下所有的 .pdbqt 文件。 |
| 3 | Grid Box 尺寸 (Size X Y Z) (对接盒子的大小) | 优先使用上次的尺寸; 无历史记录时默认为 | 支持简写,例如只输入一个数字 30,脚本会自动将其等同于 30 30 30。 |
| 4 | 中心坐标 (Center X Y Z) (对接盒子的中心位置) | 优先使用上次的坐标; 无历史记录时默认为 | 必须用空格分隔三个坐标值。如果格式输入错误,会自动回退到默认值。 |
输入准备
- receptor的pdbqt (只支持一个receptor)
- 一个文件夹,还有所有你要测试用的ligand的pdbqt(一文件夹得pdbqt)
- config中的参数,如center xyz,预测口袋size等。
脚本内容
注意!脚本中有module restore 内容,如果你的环境中直接就有autodock vina环境就可以删去,别的直接可以使用!下面是脚本内容:
#!/bin/bash
# 开启严格模式:遇到未定义变量报错,管道错误报错
set -u
set -o pipefail
ENV_FILE=".dockenv"
echo "=================================================="
echo " AutoDock Vina 批量自动化运行脚本 "
echo "=================================================="
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/.dockenv"
if [ -f "$ENV_FILE" ]; then
echo "[INFO] 检测到历史配置文件 $ENV_FILE,正在加载默认值..."
# 临时关闭 set -u 以防旧环境文件缺失某些变量
set +u
source "$ENV_FILE"
set -u
else
echo "[INFO] 未在脚本目录检测到历史配置,将使用系统内置默认值。"
fi
# 给所有潜在的变量设置“系统保底默认值”(如果 .dockenv 里没有的话)
DEFAULT_SIZE_X="${LAST_SIZE_X:-24}"
DEFAULT_SIZE_Y="${LAST_SIZE_Y:-24}"
DEFAULT_SIZE_Z="${LAST_SIZE_Z:-24}"
DEFAULT_CENTER_X="${LAST_CENTER_X:-0}"
DEFAULT_CENTER_Y="${LAST_CENTER_Y:-0}"
DEFAULT_CENTER_Z="${LAST_CENTER_Z:-0}"
DEFAULT_LIGAND_DIR="${LAST_LIGAND_DIR:-.}"
# 1. 交互式获取 Receptor (受体文件)
while true; do
if [ -n "${LAST_RECEPTOR:-}" ]; then
read -e -p "请输入 Receptor 文件路径 (直接回车默认: $LAST_RECEPTOR): " RECEPTOR
[ -z "$RECEPTOR" ] && RECEPTOR="$LAST_RECEPTOR"
else
read -e -p "请输入 Receptor 文件路径 (e.g., receptor.pdbqt): " RECEPTOR
fi
if [ -f "$RECEPTOR" ]; then
break
else
echo "[错误] 找不到该文件,请重新输入!"
fi
done
# 2. 交互式获取 Ligand 目录 (配体文件夹)
while true; do
if [ -n "${LAST_LIGAND_DIR:-}" ]; then
read -e -p "请输入 Ligand 配体目录路径 (直接回车默认: $LAST_LIGAND_DIR): " LIGAND_DIR
[ -z "$LIGAND_DIR" ] && LIGAND_DIR="$LAST_LIGAND_DIR"
else
read -e -p "请输入 Ligand 配体目录路径 (e.g., ./ligands): " LIGAND_DIR
fi
if [ -d "$LIGAND_DIR" ]; then
# 移除末尾的斜杠以保持路径整洁
LIGAND_DIR="${LIGAND_DIR%/}"
break
else
echo "[错误] 找不到该目录,请重新输入!"
fi
done
# 3. 检查目录下是否存在 .pdbqt 文件
shopt -s nullglob
LIGANDS=("$LIGAND_DIR"/*.pdbqt)
shopt -u nullglob
TOTAL_LIGANDS=${#LIGANDS[@]}
if [ "$TOTAL_LIGANDS" -eq 0 ]; then
echo "[错误] 在目录 '$LIGAND_DIR' 下未找到任何 .pdbqt 文件!脚本退出。"
exit 1
else
echo "[INFO] 成功识别到 $TOTAL_LIGANDS 个配体分子文件。"
fi
# 4. Grid Box 尺寸 (Size)
read -e -p "请输入 Grid Box 尺寸 Size (直接回车默认: $DEFAULT_SIZE_X $DEFAULT_SIZE_Y $DEFAULT_SIZE_Z): " USER_SIZE
if [ -z "${USER_SIZE}" ]; then
SIZE_X="$DEFAULT_SIZE_X"
SIZE_Y="$DEFAULT_SIZE_Y"
SIZE_Z="$DEFAULT_SIZE_Z"
else
read -r SIZE_X SIZE_Y SIZE_Z <<< "$USER_SIZE"
[ -z "$SIZE_Y" ] && SIZE_Y=$SIZE_X
[ -z "$SIZE_Z" ] && SIZE_Z=$SIZE_X
fi
# 5. 中心坐标 (Center XYZ)
read -e -p "请输入中心坐标 Center X Y Z (空格分隔, 直接回车默认: $DEFAULT_CENTER_X $DEFAULT_CENTER_Y $DEFAULT_CENTER_Z): " USER_CENTER
if [ -z "${USER_CENTER}" ]; then
CENTER_X="$DEFAULT_CENTER_X"
CENTER_Y="$DEFAULT_CENTER_Y"
CENTER_Z="$DEFAULT_CENTER_Z"
else
read -r CENTER_X CENTER_Y CENTER_Z <<< "$USER_CENTER"
if [ -z "$CENTER_X" ] || [ -z "$CENTER_Y" ] || [ -z "$CENTER_Z" ]; then
echo "[错误] 坐标格式不正确!自动回退至上一级默认值。"
CENTER_X="$DEFAULT_CENTER_X"
CENTER_Y="$DEFAULT_CENTER_Y"
CENTER_Z="$DEFAULT_CENTER_Z"
fi
fi
# ==================================================
# 参数持久化:任务成功前,将当前参数缓存写入 .dockenv
# ==================================================
cat << EOF > "$ENV_FILE"
LAST_RECEPTOR="$RECEPTOR"
LAST_LIGAND_DIR="$LIGAND_DIR"
LAST_SIZE_X="$SIZE_X"
LAST_SIZE_Y="$SIZE_Y"
LAST_SIZE_Z="$SIZE_Z"
LAST_CENTER_X="$CENTER_X"
LAST_CENTER_Y="$CENTER_Y"
LAST_CENTER_Z="$CENTER_Z"
EOF
echo "[INFO] 当前运行参数已成功缓存至 $ENV_FILE"
echo "[INFO] 开始进入批量对接循环流程..."
# 加载环境模块 (只需加载一次)
module --force purge
module restore autodock-vina
# 6. 遍历配体进行批量对接
CURRENT_COUNT=0
for LIGAND in "${LIGANDS[@]}"; do
((CURRENT_COUNT++))
# 提取配体文件名(去除路径和后缀)
LIGAND_BASE=$(basename -- "$LIGAND")
LIGAND_NAME="${LIGAND_BASE%.pdbqt}"
# 自动命名输出文件:配体名_docking.pdbqt
FINAL_OUTPUT="${LIGAND_NAME}_docking.pdbqt"
# 自动处理重名逻辑(如果当前目录下已存在,则加计数器)
if [ -e "$FINAL_OUTPUT" ]; then
counter=1
while [ -e "${LIGAND_NAME}_docking_${counter}.pdbqt" ]; do
((counter++))
done
FINAL_OUTPUT="${LIGAND_NAME}_docking_${counter}.pdbqt"
fi
echo ""
echo "=================================================="
echo " 正在处理进度: [$CURRENT_COUNT/$TOTAL_LIGANDS] "
echo " 当前配体: $LIGAND_BASE"
echo " 输出文件: $FINAL_OUTPUT"
echo "=================================================="
# 动态生成当前配体的 config.txt
cat << EOF > config.txt
# 受体和配体设置
receptor = $RECEPTOR
ligand = $LIGAND
out = $FINAL_OUTPUT
# 网格中心与大小 (Grid Box)
center_x = $CENTER_X
center_y = $CENTER_Y
center_z = $CENTER_Z
size_x = $SIZE_X
size_y = $SIZE_Y
size_z = $SIZE_Z
# 搜索参数
exhaustiveness = 32
num_modes = 20
energy_range = 3
EOF
# 动态建立日志文件
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
LOG_FILE="autodock_${LIGAND_NAME}_${TIMESTAMP}.out"
FINAL_OUTPUT_FULL_PATH=$(realpath "$FINAL_OUTPUT")
cat << EOF > "$LOG_FILE"
==================================================
VINA RUN EXECUTION DETAILS (BATCH MODE)
==================================================
Execution Time: $(date)
Receptor File: $(realpath "$RECEPTOR")
Ligand File: $(realpath "$LIGAND")
Output File: $FINAL_OUTPUT_FULL_PATH
Grid Center: X=$CENTER_X, Y=$CENTER_Y, Z=$CENTER_Z
Grid Size: X=$SIZE_X, Y=$SIZE_Y, Z=$SIZE_Z
==================================================
EOF
# 执行 Vina 对接并将输出同步重定向至日志
vina --config config.txt --cpu 2 2>&1 | tee -a "$LOG_FILE"
done
# 清理临时生成的最后一个 config.txt
[ -f config.txt ] && rm config.txt
echo ""
echo "=================================================="
echo " 所有配体分子批量对对接任务完成!共 $TOTAL_LIGANDS 个文件。 "
echo "=================================================="