第3章:校验环境搭建——bcftools、vcftools、Python的安装与配置
环境搭建这事儿,说简单也简单,说麻烦也挺麻烦。我这些年折腾过不少服务器的环境,从 CentOS 6 到 Ubuntu 22,从只有 root 权限的集群到只能在自己目录里装的笔记本,踩过的坑能写个小本子。这一章我就把几个最常用的工具——bcftools、vcftools 和 Python 生态——的安装和配置给你捋清楚。
3.1 总体选型:我为什么推荐这套组合
做 VCF 校验,你手头不能只有一把锤子。我个人的组合是:
- bcftools:主力工具,filter、norm、merge、stats 全包
- vcftools:老牌工具,做格式转换、群体统计很稳
- Python + pysam / cyvcf2:处理那些批量逻辑或者自定义规则
三者的关系,你可以看下面这张图:
说白了,bcftools 和 vcftools 帮你搞定 80% 的标准校验,剩下 20% 的骚操作,交给 Python。我早期没有用 Python,只靠命令行硬拼,结果遇到一个“等位基因频率逐样本筛选”的需求,写了半天的 shell 管道,最后还跑错了。后来换成 pysam,20 行代码就解决了。
3.2 bcftools 安装:conda 还是源码?
推荐方式:用 conda 环境管理,隔离干净,升级方便。
我个人习惯用 conda 来做环境隔离。你想想看,不同项目可能依赖不同版本的 htslib,要是全装到系统里,迟早出问题。
3.2.1 Conda 安装(最省心)
conda create -n vcf_check -c bioconda bcftools
conda activate vcf_check
bcftools --version
这样就装好了。输出里会看到版本号和编译时用到的 htslib 版本。我在项目中遇到过一个问题:conda 安装后默认用的 htslib 版本比较新,结果读一个旧版测序公司给的 BCF 文件,报了个“unsupported format version”。后来指定了旧版通道才解决。
小技巧:如果网络慢,可以在 conda 命令里加上 -c conda-forge -c bioconda 顺序,先走 conda-forge 再走 bioconda,依赖解析会顺利很多。
3.2.2 源码编译(性能优先)
如果你需要在超算上跑超大 VCF,或者想要最新的开发版功能,那就编译源码。我一般这样操作:
git clone https://github.com/samtools/bcftools.git
cd bcftools
git checkout tags/1.21 # 稳定版
make -j 4
make install # 需要 root 或指定 --prefix
嗯,这里要注意:编译前必须装好 zlib、bzip2、lzma 等压缩库。不然你可能会在运行时报错。
# 常见依赖安装 (Ubuntu)
sudo apt install libbz2-dev liblzma-dev libcurl4-openssl-dev
我曾经在编译时漏了 liblzma-dev,结果 bcftools 能跑,但遇到 .vcf.gz 就报“file format error”。后来排查半天才发现是压缩库没对齐。所以我会在编译后用几个小文件测试下。
3.3 vcftools 安装:老牌工具,依然能打
vcftools 虽然这些年更新不频繁了,但那些经典功能——比如 vcf-to-tab、--relatedness、--fst——你很难找到替代品。我的看法是:vcftools 在群体遗传领域的地位,短时间没人能撼动。
3.3.1 Conda 安装
conda install -c bioconda vcftools
3.3.2 源码安装(带 perl 模块)
有些 vcftools 的辅助脚本是 Perl 写的,比如 fill-aa、vcf-concat 这些。源码编译可以保证 perl 模块也装上。
git clone https://github.com/vcftools/vcftools.git
cd vcftools
./autogen.sh
./configure --prefix=/usr/local
make -j 4
make install
我个人更喜欢系统级安装 vcftools,因为它一般不常更新,装一次能用好几年。不过要注意,源码编译需要先装 autoconf、automake 这些工具。
避坑指南:我曾经遇到 vcftools 读取大文件时内存暴涨。后来发现是它默认把整个 VCF 读到内存里的。建议配合 bcftools 先对 VCF 做轻量过滤,再喂给 vcftools。
3.4 Python 环境:pysam 和 cyvcf2 二选一
Python 这块,核心是两个库:pysam(门槛低,社区大)和 cyvcf2(速度快,适合批量)。我一般两个都装,按场景切换。
3.4.1 创建专用环境
conda create -n vcf_py python=3.10
conda activate vcf_py
pip install pysam cyvcf2 pandas
pandas 是可选的,但我习惯在输出校验报告时用它做数据框操作。
3.4.2 pysam 快速上手
pysam 底层包装了 htslib,接口设计得很 Pythonic。下面这段代码,你可以直接拿来读 VCF 并检查一些基础字段。
import pysam
vcf = pysam.VariantFile("input.vcf.gz", "r")
for rec in vcf:
# 检查 ALT 是否为标准碱基
alleles = [rec.ref] + list(rec.alts) if rec.alts else [rec.ref]
for a in alleles:
if set(a.upper()) - set("ACGTN"):
print(f"非标准碱基在 {rec.chrom}:{rec.pos}")
break
vcf.close()
个人经验:pysam 的 fetch() 方法可以可以只读某个区间:vcf.fetch("chr1", 10000, 20000)。如果你要校验百万级的 VCF,建议用 fetch 分区域处理,别一口气全读。
3.4.3 cyvcf2 的优势
cyvcf2 是用 Cython 写的,读取速度比 pysam 快 2-3 倍。特别适合那种“我需要把整个 VCF 的某个字段都拿出来做个统计分析”的场景。
from cyvcf2 import VCF
vcf = VCF("input.vcf.gz")
for variant in vcf:
# variant.QUAL 是 PHRED 质量值,低于 20 的标记为可疑
if variant.QUAL is not None and variant.QUAL < 20.0:
print(f"Low QUAL at {variant.CHROM}:{variant.POS}")
vcf.close()
3.5 环境验证:装完到底能不能用?
装好工具不等于环境就通了。我遇过好几次,bcftools 能跑“--version”,但一读真实 VCF 就报错。所以我建议你把下面这个“冒烟测试”脚本跑一遍:
# 1. 生成一个最小的测试 VCF
echo -e "##fileformat=VCFv4.2\n##FORMAT=\n#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\tSAMPLE\nchr1\t100\t.\tA\tG\t30\tPASS\t.\tGT\t0/1" > test.vcf
# 2. 测试 bcftools 压缩与索引
bgzip test.vcf
tabix -p vcf test.vcf.gz
# 3. 测试 vcftools 基本功能
vcftools --gzvcf test.vcf.gz --out test_check --freq
# 4. 测试 Python 库
python -c "import pysam; v = pysam.VariantFile('test.vcf.gz'); print('pysam OK')"
python -c "from cyvcf2 import VCF; v = VCF('test.vcf.gz'); print('cyvcf2 OK')"
如果这四步都没报错,环境就算过了。我会把这个脚本写成 makefile,每次在新服务器上搭环境,直接 make 一遍。
注意:bgzip 和 tabix 是 HTSlib 的工具,一般随 bcftools 一起装了。如果运行时报“command not found”,你需要再单独安装:conda install -c bioconda tabix。
3.6 环境管理小建议
最后,我分享一个我在大型项目里的做法:用一个 environment.yaml 文件把整条工具链锁死版本。
name: vcf_check
channels:
- conda-forge
- bioconda
dependencies:
- bcftools=1.21
- vcftools=0.1.16
- htslib=1.21
- python=3.10
- pysam=0.22.1
- cyvcf2=0.30.18
- pandas=2.2.0
这样不管换到哪个同事的机器上,或者搬家到云上,只要 conda env create -f environment.yaml 一下,环境就完全一致。我以前吃过版本不对应的亏,两个机器上跑同样的脚本,结果因为 bcftools 版本不同,filter 的语义有细微差异,输出结果差了好几千条记录。从那以后,我就坚持锁版本了。
好了,环境搞定。接下来就可以进入真正的校验环节了。