Samtools:SAM/BAM格式操作全解
Samtools 是处理比对文件的标准工具——转格式、排序、建索引、统计、过滤、提取区域,几乎每个生信流程都会用到。本文把 Samtools 的常用子命令逐一拆解:SAM/BAM 格式解读、CIGAR 字符串、FLAG 解码、samtools view/sort/index/flagstat/stats/idxstats,附参数选择依据。
实测环境:Debian 13,Samtools v1.23.1,Conda 安装。
1. SAM/BAM 格式——知道结构才能灵活用
1.1 SAM 文件长什么样
SAM(Sequence Alignment Map)是纯文本格式,分两部分:
Header(以 @ 开头,元数据)@HD VN:1.6 SO:coordinate # 格式版本 + 排序方式@SQ SN:chr1 LN:248956422 # 染色体名 + 长度@RG ID:sample1 SM:sample1 # Read Group 信息
Body(tab分隔的11个必填字段)read1 0 chr1 100 42 50M * 0 0 ATCG... IIII...| 列号 | 字段名 | 含义 | 示例 |
|---|---|---|---|
| 1 | QNAME | Read名称 | read1 |
| 2 | FLAG | 位标志(比对信息编码) | 0=正向唯一比对 |
| 3 | RNAME | 参考序列名 | chr1 |
| 4 | POS | 比对起始位置(1-based) | 100 |
| 5 | MAPQ | 比对质量分数 | 42(Phred尺度) |
| 6 | CIGAR | 比对细节描述 | 50M(50bp完全匹配) |
| 7-9 | RNEXT/PNEXT/TLEN | mate信息 | 单端全填 * 或 0 |
| 10 | SEQ | Read序列 | ATCGATCG… |
| 11 | QUAL | 碱基质量分数 | IIII… |
1.2 CIGAR 字符串——看懂比对怎么对齐的
CIGAR 是你排查比对问题最常用到的字段:
| 操作符 | 含义 | 消耗参考 | 消耗Query |
|---|---|---|---|
| M | 匹配/错配 | 是 | 是 |
| I | 插入(Query比参考多) | 否 | 是 |
| D | 缺失(Query比参考少) | 是 | 否 |
| S | 软剪切(这部分没比对) | 否 | 是 |
| H | 硬剪切(已从SEQ中删掉) | 否 | 否 |
例子:35M1I14M = 35bp匹配 → 1bp插入 → 14bp匹配。
CIGAR 和 SEQ 长度必须一致。 计算规则:SEQ长度 = 所有 M+I+S 的碱基数之和。如果你手动编辑 SAM 文件忘了更新 CIGAR,samtools 会直接报错。
1.3 FLAG 位标志——不用死记,用工具解码
FLAG 这一列让人头疼——一个数字编码了 12 种信息:
常用的几个位:
| 位值 | 十进制 | 含义 |
|---|---|---|
| 0x1 | 1 | 双端测序 |
| 0x2 | 2 | 正确配对的read |
| 0x4 | 4 | 未比对 |
| 0x8 | 8 | mate未比对 |
| 0x10 | 16 | 比对到反链 |
| 0x40 | 64 | Read 1 |
| 0x80 | 128 | Read 2 |
| 0x100 | 256 | 非主要比对 |
| 0x400 | 1024 | PCR/光学重复 |
不用手算。 samtools flags 帮你解码:
samtools flags 83# 输出:# 0x53 83 PAIRED,PROPER_PAIR,MREVERSE,READ1# 解读:双端、正确配对、mate在反链、这是read1常见组合记忆:
99= read1 + 双端 + 正确配对 + mate反链 → RNA-seq Read1 的正常比对147= read2 + 双端 + 正确配对 + 自身反链 → RNA-seq Read2 的正常比对4= 未比对 → 这条read没比对上,但保留在文件里
2. samtools 核心子命令实操
2.1 view——转换格式和过滤
# SAM→BAM(-b = BAM输出,-S = SAM输入)samtools view -bS input.sam > output.bam
# BAM→SAM(人类可读)samtools view -h input.bam | head -20
# 过滤:只保留比对成功且MAPQ≥30的readssamtools view -b -F 4 -q 30 input.bam > filtered.bam
# 提取特定染色体区域samtools view -b input.bam chr1:1000-5000 > region.bam
# 统计比对的reads数samtools view -c -F 4 input.bam # 总比对readssamtools view -c -f 2 input.bam # 正确配对的reads参数详解:
-F 4:排除 FLAG 含 bit 4(未比对)的 reads → 只要比对上的-f 2:只要 FLAG 含 bit 2(正确配对)的 reads-q 30:MAPQ≥30(错误率 < 0.1%)
MAPQ 阈值怎么选?
| MAPQ | 正确率 | 适用场景 |
|---|---|---|
| 0 | 不确定 | 多重比对,不推荐用于变异检测 |
| 10 | 90% | 太低了,基本不用 |
| 20 | 99% | RNA-seq 表达定量可以接受 |
| 30 | 99.9% | 变异检测推荐 |
| 60 | 99.9999% | 唯一比对,最严格 |
生信流程通常用 -q 20(RNA-seq)或 -q 30(WGS 变异检测)。
2.2 sort——按坐标排序
不排序的 BAM 文件很多下游工具拒绝处理。 排序方式有两种:
# 按染色体坐标排序(默认,最常用)samtools sort input.bam -o sorted.bam
# 按read名称排序(用于某些特殊工具如Picard)samtools sort -n input.bam -o name_sorted.bam
# 指定临时目录 + 多线程加速(大文件必用)samtools sort -@ 8 -T /tmp/samtools_tmp input.bam -o sorted.bam-T 指定临时目录很重要。samtools sort 需要额外的磁盘空间做归并排序——如果 /tmp 满了会直接报错。
2.3 index——创建索引
索引让你可以快速访问 BAM 文件的任意区域:
samtools index sorted.bam
# 生成 sorted.bam.bai(或 sorted.bam.csi)# .bai 支持到 2^29 bp 的基因组# .csi 支持到 2^37 bp(超大基因组用)samtools index -c sorted.bam # 强制生成 .csi有了索引才能用 samtools view chr1:1000-5000 这种区域查询,否则需要扫描整个文件。
2.4 flagstat——快速统计看数据质量
这是我拿到比对文件后跑的第一个命令:
samtools flagstat sorted.bam输出解读:
100000 + 0 in total (QC-passed reads + QC-failed reads) 95000 + 0 primary mapped (95.00%) # 比对率 90000 + 0 properly paired (90.00%) # 正确配对率关键指标:
- 比对率(mapped rate) > 70% 正常,< 60% 可能参考基因组不对或污染
- 正确配对率(properly paired)接近比对率才正常——差异大说明文库插入片段异常
- duplicates 看 PCR 重复程度
2.5 stats——更详细的统计
samtools stats sorted.bam > stats.txt
# 用 plot-bamstats 画图(samtools 自带的小工具)plot-bamstats -p stats_plot stats.txt输出里有几个关键指标:
SN raw total sequences: 100000SN reads mapped: 95000SN reads properly paired: 90000SN insert size average: 250.5SN insert size standard deviation: 80.3插入片段长度是质控指标之一——标准偏差太大说明文库质量不稳定。
2.6 idxstats——每个染色体多少 reads
samtools idxstats sorted.bam输出四列:染色体名、染色体长度、比对上的 reads 数、未比对的 reads 数。
做 RNA-seq 的注意: 如果你看到 Y 染色体有大量 reads 而样本是女性——说明可能有比对偏差或污染。
3. 实用组合拳
提取特定区域并统计深度
# 看BRCA1基因区域的覆盖度samtools depth -r chr17:43044295-43125483 sorted.bam | \ awk '{sum+=$3; count++} END {print "Mean depth:", sum/count}'筛出低质量比对用于排查
# 找出MAPQ=0的reads(多重比对),看它们在哪些区域聚集samtools view -q 0 -Q 1 sorted.bam | cut -f3 | sort | uniq -c | sort -rn | head批量统计多个BAM的比对率
for bam in *.bam; do mapped=$(samtools flagstat "$bam" | grep "mapped (" | head -1 | cut -d' ' -f1) echo "$bam: $mapped reads mapped"done4. 踩坑记录
坑1:samtools sort 报 “No space left on device”
症状:sort 到一半崩溃。
原因:samtools sort 需要临时磁盘空间,大约是 BAM 文件的 1.5-2 倍。/tmp 在根分区且空间不够。
# 检查 /tmp 剩余空间df -h /tmp
# 指定大磁盘作为临时目录samtools sort -T /data/tmp_sort -@ 8 input.bam -o sorted.bam坑2:BAM 文件很大但 flagstat 显示 0 mapped
原因:SAM 转 BAM 时忘了加 -h 参数,header 丢了。没有 SQ header,samtools 不知道有哪些染色体。
# 正确做法:加 -h 保留 headersamtools view -bSh input.sam > output.bam
# 检查 headersamtools view -H output.bam | head坑3:idxstats 显示某染色体 reads 数是 0 但 IGV 里能看到
原因:BAM 文件里的染色体名跟 FASTA 索引的不一致。比如 BAM 里写 chr1,但索引里是 1(没前缀)。
# 看看你的 BAM 用了什么染色体名samtools idxstats sorted.bam | head -5
# 看看参考基因组的染色体名grep "^>" ref.fa | head -5如果确实不一致,用 sed 统一或重新比对。
坑4:samtools view 过滤后 reads 数不符合预期
比如 samtools view -c -F 4 -f 2 想统计”正确配对的reads”,结果比 -F 4 少很多。
原因:-F 4 和 -f 2 是不同级别的过滤——很多 reads 虽然比对上了(-F 4),但 mate 的比对质量差导致不满足”proper pair”条件。这是正常的,关键是看比例是否合理。
5. 小结
| 子命令 | 一句话作用 | 最常用参数 |
|---|---|---|
| view | 转格式+过滤 | -bS(SAM→BAM), -F 4(去未比对), -q 30(MAPQ) |
| sort | 排序 | -@ 8, -T /data/tmp, -n(按名称) |
| index | 建索引 | 直接跑,生成 .bai |
| flagstat | 快速统计 | 拿到BAM后第一件事 |
| stats | 详细统计 | 搭配 plot-bamstats 画图 |
| depth | 覆盖深度 | -r chr:start-end |
| idxstats | 染色体统计 | 检查染色体命名一致性 |
本文于 2025-03-05 在 Debian 13 上实测完成。Samtools v1.23.1,所有命令均验证通过。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!