从入行干生信到现在,我几乎每个项目都离不开samtools。不管是RNA-seq、WGS还是扩增子分析,比对完之后第一件事基本就是它。总有人问我,samtools不是一条命令就装好了吗?有什么好讲的?但真正用起来就会发现,版本、依赖、参数、坑一个都不少。这篇就把最新版samtools的安装和日常使用完整捋一遍,从零开始,该给的命令都给你,该避的坑也都标出来。
这套内容适合几类人看:刚接触NGS数据分析、被导师丢来一个比对结果不知道怎么下手的新手;已经在用samtools但一直用老版本、想升级到新版又怕搞坏环境的同学;还有那些被各种报错折磨到想删库跑路的人。读完你能搞清楚三件事:怎么干净地装上最新版,怎么用核心命令完成从SAM到BAM再到统计报告的全流程,以及遇到常见报错时怎么快速定位。
1. 版本选择和安装方案对比:先想清楚再动手
1.1 为什么建议装最新版
samtools的版本迭代一直很活跃。早期0.1.x系列是很多人入门的版本,从1.0开始代码库重构,底层统一使用htslib,后续版本的性能、压缩率、新功能都在持续改进。到写这篇文章为止,稳定版已经到1.20和1.21这个区间,GitHub上Release页面能直接看到最新tag。
新版带来的不只是版本号的变化。1.10之后默认输出格式、部分命令行为都有调整,比如直接支持CRAM的读写优化、对long reads比对数据的处理更友好、sort和index等高频命令的性能明显提升。更重要的是,很多下游工具会检查samtools版本,老版本在某些环节会产生不兼容的中间文件,排查起来非常痛苦。
我一直建议生产环境至少保持一年内更新的版本,而不是守着五年前装好的0.1.19用到底。新版命令的基本用法和旧版保持一致,升级成本很低,但性能和兼容性的收益很可观。
1.2 三种主流安装方式对比
安装samtools主要有源码编译、conda安装、系统包管理器安装三条路。
系统包管理器最省事,比如Ubuntu上执行sudo apt install samtools,RHEL系用yum install samtools。但问题是版本通常滞后,apt源里的版本往往落后官方一两年。如果只是偶尔看看BAM文件,不是不行,但要做严谨的分析我一般不推荐。
conda方案适合已经有Anaconda或Miniconda环境的人。bioconda频道维护得很及时,新版本发布后很快就能跟进,而且依赖关系处理得比较好,安装后基本开箱即用。这个方案对环境隔离也友好,不同项目可以用不同环境装不同版本,互不干扰。
源码编译是唯一能保证拿到官方最新版本、并且可以自定义安装路径的方式。编译过程不算复杂,主要是把依赖库装齐、配置好编译器。服务器上没网或者内网环境时,源码包也是最方便拷贝进去安装的。
先给出一张对比表,后面详细拆解:
| 安装方式 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| apt/yum 系统包 | 安装最快 | 版本旧 | 临时查看、非生产 |
| conda | 版本新、依赖自动 | 依赖conda环境 | 个人分析、多版本共存 |
| 源码编译 | 版本最新、可自定义 | 需处理依赖 | 生产环境、内网服务器 |
2. 源码编译安装完整实操:从依赖到验证
2.1 编译前的依赖准备
源码编译samtools前,先确认系统有gcc、make、autoconf、automake这些基础工具。在Ubuntu/Debian上执行:
sudo apt update sudo apt install -y build-essential autoconf automake libbz2-dev liblzma-dev libcurl4-openssl-dev libncurses5-dev libdeflate-dev zlib1g-devCentOS/RHEL系用yum对应安装gcc gcc-c++ make autoconf automake bzip2-devel xz-devel libcurl-devel ncurses-devel zlib-devel libdeflate-devel。
这几个依赖里,zlib管gzip压缩,liblzma管XZ压缩,libbz2管bzip2压缩,libcurl用于支持从URL直接读取数据,libncurses用于tview和mpileup等交互式界面的字符渲染。少任何一个都可能让你在某个环节莫名其妙的报错。
注意:新版samtools在编译时还会自动构建htslib,源码目录里会包含htslib子模块。如果从GitHub克隆仓库,记得加
--recursive参数把子模块拉全,否则编译到一半会报缺文件。
2.2 下载源码并编译安装
从GitHub官方仓库下载最新版源码包,用wget拉到服务器:
wget https://github.com/samtools/samtools/releases/download/1.21/samtools-1.21.tar.bz2 tar -xjf samtools-1.21.tar.bz2 cd samtools-1.21然后按标准三步走配置、编译、安装:
./configure --prefix=/opt/samtools/1.21 make -j 8 make install--prefix参数指定安装目录,我习惯装到/opt/samtools/1.21这种带版本号的路径,方便以后升级切换。-j 8表示用8个线程并行编译,服务器核心数多可以调大,慢的时候主要是没有并行导致的,8核机器上一两分钟就能编完。
编译完成后,把可执行文件加到PATH环境变量里:
export PATH=/opt/samtools/1.21/bin:$PATH为了每次登录都不用手动设置,把这行追加到~/.bashrc文件末尾,然后执行source ~/.bashrc。如果系统里之前已经装过旧版samtools,注意PATH的优先级,确保which samtools指向的是新装的位置。
2.3 conda安装方式参考
如果你已经有conda环境,安装更简单:
conda create -n bioinfo -c conda-forge -c bioconda samtools=1.21 conda activate bioinfo samtools --version不指定版本号默认装最新版,但我是建议分析项目里固定版本,否则哪天更新了行为变了,你都不知道结果差异是软件版本还是真实生物学差异导致的。
2.4 验证安装是否成功
安装完先看版本:
samtools --version正常情况下会输出类似:
samtools 1.21 Using htslib 1.21 Copyright (C) 2024 Genome Research Ltd.这里有个重要的判断点:samtools版本和htslib版本通常是配套的,如果出现samtools是1.21但htslib是1.10这种组合,说明环境变量或动态库链接有问题,因为新版依赖htslib的特性,旧库可能导致一些命令崩溃或结果异常。
再跑一个简单命令验证基本功能:
samtools view --help不报错、能看到完整参数列表,说明安装没问题。
3. 最核心的四条命令:view、sort、index、flagstat
安装只是开始,真正的日常使用围绕几条高频命令展开。我用一个实际的WGS分析流程来串讲。假设你刚跑完比对,拿到一个sample.sam文件,接下来要做的事就是转格式、排序、建索引、看统计。
3.1 view:格式转换和过滤
samtools view是最常用的入口命令,它负责SAM、BAM、CRAM之间的格式转换,也可以按flag、比对质量、区域来过滤reads。
最基础的操作是把SAM转成BAM:
samtools view -@ 8 -b sample.sam > sample.bam-b指定输出BAM格式,-@ 8用8个线程,SAM文件大时可以明显提速。新版samtools也能直接自动识别输入格式,上面命令等价于:
samtools view -@ 8 -b -o sample.bam sample.sam过滤比对的reads很常用。比如只保留比对质量不低于30的reads,同时过滤掉未比对、重复、次要比对的reads:
samtools view -@ 8 -b -h -q 30 -F 0x904 -o filtered.bam sample.bam这里-q 30是质量阈值,-F 0x904是过滤flag值。flag是SAM格式里用二进制位表示比对状态的机制,0x904由0x1(paired)、0x8(unmapped)、0x400(duplicate)组合而来,-F的含义是"跳过包含这些flag的reads"。反过来-f是"只保留包含这些flag的reads",比如只看比对上的read:
samtools view -b -f 0x2 sample.bam > mapped_proper_pairs.bam0x2表示proper pair,即双端reads都比对到同一条染色体且方向正常。
3.2 sort:按坐标排序的关键作用
很多下游分析工具要求BAM文件按参考坐标排序,比如变异检测、IGV可视化。samtools sort就是干这个的。
samtools sort -@ 8 -m 2G -o sample.sorted.bam sample.bam-m 2G表示每个线程最多使用2GB内存做排序缓冲。注意-m是每个线程的内存配额,-@ 8配合-m 2G时理论上最多占16GB内存,要根据机器实际内存来设,别一看-OOM才知道调低。
新版本sort默认输出到标准输出,所以-o指定输出文件很关键,否则shell里会写出一大堆乱码。排序结束不会打印多余信息,但会生成一个排好序、带好索引基础的BAM文件。
我遇到不少次这种情况:有人直接从比对软件拿到sort.bam,然后拿去跑GATK,报错说索引缺失。其实比对软件常常输出的是按read name排序的文件,和坐标排序不是一回事。先跑一下head看看有没有header,再用samtools sort排一遍再说。
3.3 index:没有索引寸步难行
排序后的BAM文件需要建立索引才能被快速随机访问。执行:
samtools index sample.sorted.bam正常情况下会生成sample.sorted.bam.bai文件。如果基因组参考很大或者reads很长,默认BAI索引可能不够用,可以用-c生成CSI索引:
samtools index -c sample.sorted.bamCSI索引支持更大的基因组和更长的reads,新版samtools在检测到需要时也会自动选择。但注意,有些下游工具只认BAI格式,如果遇到"Couldn't open index"的报错,检查一下是不是用了CSI而工具不支持。
index文件的原理是把参考基因组分成bin,bin内记录reads的位置偏移,这样想提取某个区域的reads时,不需要读整个BAM文件,直接在索引里定位再跳转读取。没有这个文件,IGV里想拖到某个基因上看alignment会卡到怀疑人生。
3.4 flagstat和stats:快速看懂比对质量
做完排序和索引,第一步质检就是用flagstat看整体情况:
samtools flagstat sample.sorted.bam输出类似:
16777216 + 0 in total (QC-passed reads + QC-failed reads) 16384000 + 0 primary 114688 + 0 secondary 327680 + 0 supplementary 0 + 0 duplicates 16777216 + 0 mapped (100.00% : N/A) 16000000 + 0 paired in sequencing每一行都是一类reads的统计,最常用的是total、mapped百分比和properly paired比例。如果mapped比例很低,先怀疑比对参数、参考基因组选择或测序数据质量。注意新版flagstat对secondary和supplementary单独计数,老版本可能混在一起,查看时版本差异要心里有数。
比flagstat更详细的是stats命令,会输出包括插入片段长度分布、每条染色体的reads数、碱基质量分布等几百行指标:
samtools stats sample.sorted.bam > sample.stats.txt如果装了plot-bamstats,可以把stats输出直接画成PDF报告。这个图在生产汇报时很实用,比对率、reads分布、插入片段峰形都一目了然。
4. 进阶用法:从质检到变异检测和序列提取
4.1 depth:统计测序深度
评估测序深度是否达标,最直观的命令是depth。查看全基因组每个位点的深度分布:
samtools depth -a sample.sorted.bam > depth.out-a参数会把深度为0的位点也输出,否则默认只输出有覆盖的位点。输出文件是三列:染色体、位置、深度。用AWK统计平均深度和覆盖率:
awk '{sum += $3; count++} END {print "mean_depth:", sum/count}' depth.out限定区域计算深度也很常用,比如只看某个基因:
samtools depth -r chr1:100000-120000 sample.sorted.bam | head要统计每个靶区间的平均覆盖度,可以配合BED文件:
samtools depth -b regions.bed sample.sorted.bam > region_depth.out在实际项目中,我一般用-a输出全基因组深度,再用Python脚本按窗口滑窗统计,比单独跑stats更直观。深度分布是判断测序质量的核心指标,如果某个区域深度突然掉到0,要考虑是不是参考基因组在该位置有缺失、比对参数太严格或者测序本身有偏好。
4.2 mpileup:变异检测的入口
samtools mpileup曾经是GATK流程之外最常见的变异检测入口,它会把BAM文件转成VCF/BCF格式原料,配合bcftools完成过滤和注释。新版本建议直接使用bcftools mpileup和bcftools call,但samtools mpileup仍然广泛使用。
基本用法:
samtools mpileup -f reference.fa sample.sorted.bam > sample.pileup输出每行是一个位点的覆盖情况,包含参考碱基、覆盖该位点的reads的碱基组成。如果直接生成BCF给bcftools call:
samtools mpileup -g -f reference.fa sample.sorted.bam > sample.raw.bcf bcftools call -m -O v -o sample.vcf sample.raw.bcf关于-g参数:新版samtools里输出BCF格式时-g已经不再必须,但加上它明确表示输出格式,不容易出错。注意mpileup极其吃内存和磁盘,全基因组数据跑一次可能要几十GB磁盘,大批量样本建议分染色体并行跑。
实际项目中,如果做WGS单核苷酸变异检测,我现在更推荐bcftools mpileup | bcftools call的组合,因为下游过滤和质量控制工具更丰富。但命令行平台、教学示例里samtools mpileup依然是经典,理解它的输出格式对后续手动检查变异位点非常有帮助。
4.3 faidx:对参考基因组建索引和提取序列
faidx的核心作用是给FASTA格式的参考基因组建立索引文件,再按区域提取序列。第一次用参考基因组前先建索引:
samtools faidx reference.fa生成reference.fa.fai文件,记录每条染色体的长度、偏移量等信息。之后就能按区域快速提取序列:
samtools faidx reference.fa chr1:10000-10100输出是FASTA格式的序列。这个功能在设计PCR引物、检查变异位点附近的参考序列、从大基因组中截取目标片段时非常实用。用一句话形容就是"按书签翻书",没有索引就必须从头读到尾,有了索引直接翻到目标页。
4.4 merge和markdup:文件合并与重复标记
多批次测序数据通常需要合并成一个BAM文件再统一分析。samtools merge是最简单的方案:
samtools merge -@ 8 merged.bam sample1.sorted.bam sample2.sorted.bam sample3.sorted.bam注意:合并前必须确保所有输入的BAM都用同一参考基因组比对,且已经排序。不同参考版本的BAM合并后,下游分析会一塌糊涂,chr命名都不一致时哪些是重复序列更说不清。
重复标记方面,老流程常用Picard MarkDuplicates,但新版samtools的markdup已经能满足常规去重需求,速度更快:
samtools markdup -@ 8 -s sample.sorted.bam sample.markdup.bam-s参数表示单独输出重复reads的统计信息到标准错误。markdup要求输入文件是坐标排序且已经建立了索引,并且reads名字不能有重复。如果报错提示需要先执行collate,按提示跑一下:
samtools collate -@ 8 -O sample.sorted.bam sample.collate.bam samtools fixmate -@ 8 -m sample.collate.bam sample.fixmate.bam samtools sort -@ 8 -o sample.fixmate.sorted.bam sample.fixmate.bam samtools markdup -@ 8 -s sample.fixmate.sorted.bam sample.markdup.bam这条链路的原理是:collate让reads按名字排到一起,fixmate把插入片段信息补上,sort再恢复坐标排序,最后markdup识别并标记重复。流程看起来绕,但对双端数据来说这才能正确计算片段长度并准确区分PCR重复和真实生物学重复。
5. 常见报错和日常排坑速查
用samtools久了,最怕的不是功能不会用,而是碰到各种报错后一脸懵。我把这些年频繁踩过的坑整理成速查表,每一条都是真实项目中遇到过的。
| 报错或现象 | 可能原因 | 解决办法 |
|---|---|---|
samtools: command not found | PATH没配置或未安装 | which samtools确认,重装或补export PATH |
[E::hts_open] fail to open file | 输入文件路径错误或权限不足 | 检查文件是否存在、有无读取权限 |
[bam_header_read] EOF | 读取的文件不是完整BAM头 | 确认文件是否是由SAM转换而来、用less看文件头 |
truncated file | BAM文件不完整,传输中断 | 重新拷贝/重新生成BAM |
[E::idx_find_and_load] Could not retrieve index | 索引缺失或文件名不匹配 | 执行samtools index生成索引 |
[bam_sort_core] truncated file | 输入BAM本身损坏 | 先view确认原文件完整再排序 |
CRAM file is not supported | 编译时没开启CRAM支持 | 重新编译时装上libcurl、libdeflate |
| 版本太旧导致某些命令参数变化 | 例如fillmd在1.10后被移除 | 查1.x版本的命令变更说明,改用新参数 |
再单列几个容易忽视的细节:
第一,samtools mpileup的输出文件如果非常大,建议不要直接重定向到文本,而是先用-g输出BCF,后续需要看时用bcftools view转换。文本pileup全基因组可能要上百GB,而BCF是压缩的,几个G就能装下。
第二,很多人不知道samtools view的-L参数可以直接传入BED文件过滤区间,作用等同于先提取区间再过滤,但效率高很多,因为它会在读取时直接跳过不在区间内的reads。处理大BAM时能少读一大半数据。
第三,新版samtools对stdin/stdout的处理更严格。比如管道组合时,-o如果不写会很糟糕。养成每个命令都显式写输入输出文件的习惯,避免把二进制数据打到终端上卡死。
我踩过一次最深的坑是:服务器上同时装了conda环境和系统自带samtools,用conda activate激活环境后which samtools指向的是新版本,但脚本里却用绝对路径调用了老版本,导致整个流程的flag计算结果差异很大。后来我统一在所有脚本开头用module purge或unalias清理旧环境,再显式export新版本路径,这个问题才彻底解决。
还有一次全基因组测序数据处理到一半,突然samtools sort报错内存不够。查看后是-m参数设了4G但机器总内存只有8G,加上-@ 4一共要16G,直接把机器跑死。正确做法是先free -h看机器可用内存,合理分配线程和单线程内存,比如8G内存的机器配-@ 2 -m 2G。
从使用体验来说,新版samtools在大型数据集上确实稳得多。CRAM格式使用越来越多之后,它的优势只会更大。如果你是第一次接触生信分析,建议把samtools view、sort、index、flagstat这四个命令练到闭着眼能写出来,后面的流程基本就顺了。真想深入学的,可以在自己的测试数据上跑一遍samtools stats,然后逐字段去查解释文档,这个过程比看一百篇教程都有用。