基于haddock的蛋白—蛋白对接分析
haddock是一个以CNS为基础的算法,可以方便的进行蛋白质-蛋白质对接。基于haddock-lite进行简要筛选可以减少进一步筛选工作量。
前期准备
一.安装MobaXterm,登陆服务器
在该网址下载Xterm,作为登陆服务器的访问端:MobaXterm Xserver 支持SSH、telnet、RDP、VNC和X11 – 下载。

完成后sessions创建登陆用户及ID。通常选择SSH登陆。


Remote host写主机地址(往往是IP),specify username指定登陆者用户。在右侧添加用户(人锁图标)。

new创建新用户,name随便自己写,username为登陆用户名,password为该用户密码。完成后双击主页左侧主机即可登陆。
二.在Linux环境下安装miniconda环境,并创建家目录。
Miniconda 是 Anaconda 的轻量版,仅包含 conda、Python 及基本依赖。以下是各系统安装核心步骤:
- 下载安装包
访问官方仓库选择对应系统版本(推荐 64 位):
官网地址:https://repo.anaconda.com/miniconda/
Windows:下载 Miniconda3-latest-Windows-x86_64.exe
macOS:Intel 芯片选 x86_64,Apple Silicon (M1/M2) 选 arm64
Linux:下载 .sh 脚本文件,如 Miniconda3-latest-Linux-x86_64.sh
也可以直接执行wget从清华镜像站下载。
wget -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda-latest-Linux-x86_64.sh
- 执行安装
Windows 系统
双击 .exe 文件,点击 Next > 勾选 I Agree。
选择安装类型(推荐 Just Me),设置安装路径(建议纯英文路径,如 D:\Miniconda3)。
关键步骤:勾选 Add Miniconda3 to my PATH environment variable(自动配置环境变量),不勾选“注册为默认 Python”。
点击 Install,完成后点击 Finish 。
macOS / Linux 系统
终端进入下载目录,赋予执行权限:chmod +x Miniconda3-latest-*.sh。
运行安装:bash Miniconda3-latest-*.sh。
按回车浏览协议,输入 yes 同意。
确认安装路径(默认 ~/miniconda3),最后输入 yes 初始化 conda(修改 .bashrc)。
- 验证与激活 重启终端(必须步骤,否则命令无效)。
输入 conda –version,若显示版本号则安装成功。
若提示“命令不存在”,需手动将安装目录下的 bin (Linux/Mac) 或 Scripts/Library/bin (Windows) 加入系统 PATH 。 - 加速配置(可选)
国内网络建议配置清华镜像源以加速下载(原理相同,二选一即可):
#设置镜像通道,设置默认镜像
bash
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
#设置镜像通道,设置默认镜像
channels:
https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda
defaults
show_channel_urls: true
conda config --set show_channel_urls yes
安装后可通过 conda create -n 环境名 python=3.x 创建独立虚拟环境 。
三.安装FFTW,pdb-tool和haddock-lite。
下载fftw和haddock-lite(自行上网搜索下载)。
#安装pdb-tools
pip install pdb-tools
tar -zxvf 文件名.tar.gz
运行tar解压并安装。
配置环境变量,方便调用
./configure --prefix=$HOME/fftw --enable-shared --enable-threads --enable-openmp CFLAGS="-O3 -march=native"
export PATH="/*/fftw-3.3.11/build/bin:$PATH"
export LD_LIBRARY_PATH="/*/fftw-3.3.11/build/lib:$LD_LIBRARY_PATH"
export CPATH="/*/fftw-3.3.11/build/include:$CPATH"
export PATH="/*/HDOCKlite-v1.1:$PATH"
四.蛋白质结构清洗与预处理。
预测后蛋白结构pdb文件集中放在一个位置,方便处理。
less XXX.model_0.pdb | pdb_tidy -strict | pdb_delhetatm | pdb_selaltloc | pdb_keepcoord | pdb_chain -B | pdb_chainxseg | pdb_tidy -strict > XXX.clean.pdb
#管道命令
#less *model_0.pdb:读取文件。
#pdb_tidy -strict:格式化
#pdb_delhetatm:删除杂原子(水、配体等)
#pdb_selaltloc:处理多构象,在晶体结构中,某些柔性侧链可能存在多种构象(用 A, B, C 等标识)。这个命令默认只保留每个原子的第一个或占据率最高的构象,删除其他构象,确保每个原子只有一个坐标。
#pdb_keepcoord:只留坐标(ATOM行),删掉注释(REMARK等)
#pdb_chain -B:改链名为 B。
#pdb_chainxseg:交换 Chain ID(链标识符,第22列)和 SegID(片段标识符,通常在第73-76列)。
SegID 被广泛用来区分不同的分子链。此命令将Chain ID (B) 复制到 SegID 的位置,满足软件的输入要求。
#pdb_tidy -strict:再格式化一次,-strict参数为严格模式。
#> XXX.clean.pdb:输出结果到该PDB。
也可以用批执行来完成。下列代码中,由于文件夹名就是我所需的蛋白名,因此做了文件夹名称提取,对输出文件进行重命名。
#!/bin/bash
# 设置严格模式:任何命令失败立即退出,管道中任何步骤失败都返回错误
set -e -o pipefail
# 全局临时文件列表(用于中断时清理)
TEMP_FILES=()
# 全局清理函数(用于中断时清理所有临时文件)
cleanup_all_temp() {
if [ ${#TEMP_FILES[@]} -gt 0 ]; then
echo "" >&2
echo "清理临时文件..." >&2
rm -f "${TEMP_FILES[@]}" 2>/dev/null
TEMP_FILES=()
fi
}
# 设置全局 trap,在脚本退出或中断时清理所有临时文件
trap cleanup_all_temp EXIT INT TERM
# 错误处理函数
handle_error() {
local step=$1
local exit_code=$2
echo "ERROR: 在步骤 '$step' 中失败,退出码: $exit_code" >&2
cleanup_all_temp
exit $exit_code
}
# 检查命令是否存在
check_command() {
local cmd=$1
if ! command -v "$cmd" &> /dev/null; then
echo "ERROR: 命令 '$cmd' 未找到,请确保pdb-tools已安装并在PATH中" >&2
exit 1
fi
}
# 添加临时文件到全局列表
add_temp_file() {
local file="$1"
TEMP_FILES+=("$file")
}
# 从全局列表中移除并删除临时文件
remove_temp_file() {
local file="$1"
# 从列表中移除
for i in "${!TEMP_FILES[@]}"; do
if [ "${TEMP_FILES[$i]}" = "$file" ]; then
unset 'TEMP_FILES[$i]'
break
fi
done
# 删除文件
rm -f "$file" 2>/dev/null
}
# 处理单个PDB文件的函数
process_single_pdb() {
local pdb_file="$1"
local dir_path=$(dirname "$pdb_file")
local base_name=$(basename "$pdb_file")
echo ""
echo "======================================"
echo "处理文件: $pdb_file"
# 从文件名提取标识符(格式:fold_2026_06_03_21_10_bm_01055_model_0.pdb -> bm_01055)
identifier=$(echo "$base_name" | awk -F'_' '{print $(NF-3)"_"$(NF-2)}')
echo "提取的标识符: $identifier"
# 转换为大写作为输出文件名(bm_01055 -> BM_01055.clean.pdb)
local output_prefix=$(echo "$identifier" | tr '[:lower:]' '[:upper:]')
local output_file="${dir_path}/${output_prefix}.clean.pdb"
echo "输出文件: $output_file"
# 创建临时文件存储中间结果
local temp_file=$(mktemp)
local temp_file_tmp="${temp_file}.tmp"
# 将临时文件添加到全局列表(用于中断时清理)
add_temp_file "$temp_file"
add_temp_file "$temp_file_tmp"
# 定义局部清理函数
local cleanup_done=0
cleanup_temp() {
if [ $cleanup_done -eq 0 ]; then
remove_temp_file "$temp_file"
remove_temp_file "$temp_file_tmp"
cleanup_done=1
fi
}
# 分步骤执行处理管道
echo "[1/7] 读取PDB文件..."
if ! cat "$pdb_file" > "$temp_file"; then
cleanup_temp
handle_error "读取PDB文件" $?
fi
echo "[2/7] 执行 pdb_tidy -strict..."
if ! pdb_tidy -strict < "$temp_file" > "$temp_file_tmp"; then
cleanup_temp
handle_error "pdb_tidy -strict" $?
fi
mv "$temp_file_tmp" "$temp_file"
echo "[3/7] 执行 pdb_delhetatm..."
if ! pdb_delhetatm < "$temp_file" > "$temp_file_tmp"; then
cleanup_temp
handle_error "pdb_delhetatm" $?
fi
mv "$temp_file_tmp" "$temp_file"
echo "[4/7] 执行 pdb_selaltloc..."
if ! pdb_selaltloc < "$temp_file" > "$temp_file_tmp"; then
cleanup_temp
handle_error "pdb_selaltloc" $?
fi
mv "$temp_file_tmp" "$temp_file"
echo "[5/7] 执行 pdb_keepcoord..."
if ! pdb_keepcoord < "$temp_file" > "$temp_file_tmp"; then
cleanup_temp
handle_error "pdb_keepcoord" $?
fi
mv "$temp_file_tmp" "$temp_file"
echo "[6/7] 执行 pdb_chain -B | pdb_chainxseg..."
if ! pdb_chain -B < "$temp_file" | pdb_chainxseg > "$temp_file_tmp"; then
cleanup_temp
handle_error "pdb_chain -B | pdb_chainxseg" $?
fi
mv "$temp_file_tmp" "$temp_file"
echo "[7/7] 执行 pdb_tidy -strict..."
if ! pdb_tidy -strict < "$temp_file" > "$output_file"; then
cleanup_temp
handle_error "pdb_tidy -strict" $?
fi
# 显式清理临时文件(函数正常结束时)
cleanup_temp
echo "SUCCESS: 处理完成"
echo "输出文件: $output_file"
echo "文件大小: $(du -h "$output_file" 2>/dev/null | awk '{print $1}')"
echo "======================================"
}
# 主程序开始
echo "======================================"
echo "PDB文件批量处理脚本"
echo "======================================"
# 检查所有必需的pdb工具
echo ""
echo "检查必需的pdb工具..."
check_command "pdb_tidy"
check_command "pdb_delhetatm"
check_command "pdb_selaltloc"
check_command "pdb_keepcoord"
check_command "pdb_chain"
check_command "pdb_chainxseg"
echo "所有pdb工具检查通过"
# 递归搜索所有子文件夹中的PDB文件
echo ""
echo "搜索PDB文件..."
mapfile -t pdb_files < <(find . -type f -name "fold_*_model_*.pdb" 2>/dev/null)
if [ ${#pdb_files[@]} -eq 0 ]; then
echo "ERROR: 未找到匹配的PDB文件" >&2
echo "搜索模式: fold_*_model_*.pdb" >&2
echo "搜索范围: 当前目录及其子目录" >&2
exit 1
fi
echo "找到 ${#pdb_files[@]} 个PDB文件:"
for pdb_file in "${pdb_files[@]}"; do
echo " - $pdb_file"
done
# 处理每个PDB文件
for pdb_file in "${pdb_files[@]}"; do
process_single_pdb "$pdb_file"
done
echo ""
echo "======================================"
echo "全部处理完成!"
echo "======================================"