2. BAM文件QC失败:Read Group缺失或格式错误
说起来你可能不信,我第一次遇到 Failed to create SAMFileWriter 这个报错时,差点以为是GATK装错了。
花了整整半天重装软件,结果发现——就是BAM文件头里少了一行 @RG。我当时的表情,你想想看。
这种问题在NGS项目中其实特别常见。尤其是从公共数据库下载数据、或者让实习生跑完比对就直接丢过来的BAM,十有八九都有Read Group问题。
2.1 报错长什么样?
GATK遇到Read Group问题时的日志很有辨识度。它不会直接告诉你“老弟,你缺RG了”,而是绕个弯报个文件写入错误。我第一次看见这个报错时,脑子直接懵了。
典型报错日志长这样:
##### ERROR MESSAGE: Failed to create SAMFileWriter
##### ERROR MESSAGE: SAMFileWriterImpl detects that the header has no Read Groups defined
##### ERROR MESSAGE: Invalid: No ReadGroup tags found in the header
有时候还会跟着这个:
##### ERROR MESSAGE: The read group ID is either missing or malformed
##### ERROR MESSAGE: Pls make sure your BAM/CRAM file contains a valid @RG line
说白了,GATK就是要读你的BAM头里的 @RG 行。没有?那就罢工。
2.2 Read Group到底是什么?
Read Group说白了就是每条reads的“身份证”。它告诉GATK:这条reads是哪个样本的、哪个文库的、哪台测序仪跑出来的、哪个Lane的产物。
GATK里有个硬性规定——所有reads都必须挂载到一个Read Group下。没有挂载?直接报错。这是GATK的基因,改不了。
一个标准的 @RG 行必须包含以下字段:
| 标签 | 全称 | 含义 | 是否必填 |
|---|---|---|---|
| ID | Read Group Identifier | 唯一标识符,每个RG的唯一ID | 必填 |
| SM | Sample | 样本名称,就是你要分析的那个样本 | 必填 |
| LB | Library | 文库名称 | 必填 |
| PL | Platform/Technology | 测序平台,比如ILLUMINA、IONTORRENT | 必填 |
| PU | Platform Unit | 测序单元,通常是Flowcell+Lane组合 | 强烈建议 |
记住:ID和SM是最容易出问题的两个字段。ID要唯一,SM必须与样本名称一致。我经常看到有人把SM写成"123456"而不是"Sample_001",结果GATK直接报错。
2.3 一步一步排查
发生报错时,别慌。按这个顺序查,几乎不会漏。
-
先用samtools看看头信息
直接看
@RG行在不在。samtools view -H your_sample.bam | grep -E '@RG'如果返回为空——找到原因了,缺RG。
-
检查RG的格式
有RG行不代表万事大吉。格式错了同样崩溃。
我见过最坑的一个案例——ID后面跟了个空格,结果字符串解析成两个字段,GATK完全认不出来。
@RG ID:NGS_001 SM:S1 LB:LibA PL:ILLUMINA注意,标签名是大写的,标签值不要有中文或特殊字符。
-
确认SM字段与样本对照表一致
如果你是跑群体数据分析,SM字段必须与VCF里的样本名对应。否则后面合并GVCF时会出现样本名不匹配的问题。
我个人习惯:在正式跑GATK前,先把SM字段提出来,和样本清单做一次交叉验证。
samtools view -H your_sample.bam | grep -oP 'SM:\K\S+'确认输出就是这个样本的正确名称。
-
多RG文件的PB级别项目
在WGS超大项目中,一个样本可能有多个RG——不同Lane、不同文库。这种情况要确保同一样本的多个RG的SM字段完全一致。
我用过一个奇葩数据,同一个样本的RG里SM字段大小写不统一——一个写
Sample_A,另一个写sample_a。GATK把它们当成两个样本处理,整个分析全部跑偏。
避坑经验:我建议你专门写一个QC脚本,每次拿到新BAM先跑一轮check。检查 @RG 是否存在、SM是否与样本名一致、PL字段是否合法。我手底下的项目现在都用这个流程,从来没在这个环节再出过问题。
2.4 修复方案
发现问题了。怎么修?有三种路子。
方案一:用Picard的AddOrReplaceReadGroups
这是最推荐的做法,不乱动BAM内容,只在头信息里加RG。
java -jar picard.jar AddOrReplaceReadGroups \
I=input.bam \
O=output.bam \
RGID=Project_001 \
RGLB=Lib_A \
RGPL=ILLUMINA \
RGPU=FlowcellA_Lane1 \
RGSM=Sample_001 \
CREATE_INDEX=true
跑完后记得再用 samtools view -H 确认一下。
注意:如果你原始BAM已经有一部分RG,而你想覆盖它们——没问题,这个工具会直接替换。但如果你只是要追加RG,请小心操作,别把原有的覆盖了。
方案二:如果RG已存在但格式错了
有时候你只是某个字段写错了,比如PL写了 ILLUMINA 却写成了 Illumina。这时候用sed直接改BAM头的头信息。
我分享一条实用的命令:
samtools reheader -c 'sed "s/PL:Illumina/PL:ILLUMINA/g"' old.bam > new.bam
嗯,这个管道只改头,数据体不会动,速度很快。
方案三:从上游重跑比对
如果原始FastQ的Read Group信息就没记录对,那就只能从bwa或STAR那一步重来了。
我的建议是——在比对命令里就把RG信息写全。bwa-mem的 -R 参数:
bwa mem -R '@RG\tID:Sample_001\tSM:Sample_001\tLB:Lib_A\tPL:ILLUMINA' \
reference.fa \
Sample_001_R1.fastq.gz \
Sample_001_R2.fastq.gz \
| samtools sort -o Sample_001.bam
这里注意用 \t 替换空格,@RG后面不能有空格。
2.5 Read Group与BAM文件的关系
下面这张图可以帮你理解Read Group在整个BAM结构中的位置:
我个人习惯:我设计了一个小脚本,叫 check_rg.sh。每次跑大项目前,把这个脚本丢到所有样本的BAM上跑一遍。如果任何一个样本缺RG、SM不匹配、或者PL非法——脚本直接杀停并输出详细报告。这样做的好处是:大数据集里你不用再人工一个个看头文件了。
修复完Read Group后,再用GATK跑一遍,几乎不会再出现 Failed to create SAMFileWriter 这个问题。如果还报错?那就要看看是不是BAM路径没写对权限不对,又或者是磁盘不够了——但这些,就是另一个故事了。