目錄
- samtools和picard的排序問題
- SAM文件中FLAG值的理解
- SAM文件中那些未比對的reads
- 為什么一條read會有多條比對記錄?
- 同一份BAM文件samtools depth和samtools mpileup的結果不同?
- 為什么samtools flagstat與hisat2的mapping rate不同?
1. samtools和picard的排序問題
samtools
和picard
都有對SAM/BAM文件進行排序的功能,一般都是基于坐標排序(還提供了-n
選項來設定用reads名進行排序),先是對chromosome/contig進行排序,再在chromosome/contig內部基于start site從小到大排序,對start site排序很好理解,可是對chromosome/contig排序的時候是基于什么標準呢?
基于你提供的ref.fa
文件中的chromosome/contig的順序。當你使用比對工具將fastq文件中的reads比對上參考基因組后會生成SAM文件,SAM文件包含頭信息,其中有以@SQ
開頭的頭信息記錄,reference中有多少條chromosome/contig就會有多少條這樣的記錄,而且它們的順序與ref.fa
是一致的。
SAM/BAM文件的頭信息:
@HD VN:1.3 SO:coordinate @SQ SN:chr1 LN:195471971 @SQ SN:chr2 LN:182113224 @SQ SN:chr3 LN:160039680 @SQ SN:chr4 LN:156508116 @SQ SN:chr5 LN:151834684 @SQ SN:chr6 LN:149736546 @SQ SN:chr7 LN:145441459 @SQ SN:chr8 LN:129401213 @SQ SN:chr9 LN:124595110 @SQ SN:chr10 LN:130694993 @SQ SN:chr11 LN:122082543 @SQ SN:chr12 LN:120129022 @SQ SN:chr13 LN:120421639 @SQ SN:chr14 LN:124902244 @SQ SN:chr15 LN:104043685 @SQ SN:chr16 LN:98207768 @SQ SN:chr17 LN:94987271 @SQ SN:chr18 LN:90702639 @SQ SN:chr19 LN:61431566 @SQ SN:chrX LN:171031299 @SQ SN:chrY LN:91744698 @SQ SN:chrM LN:16299 @RG ID:ERR144849 LB:ERR144849 SM:A_J PL:ILLUMINA
ref.fa
中chromosome/contig的排列順序:>chr1 >chr2 >chr3 >chr4 >chr5 >chr6 >chr7 >chr8 >chr9 >chr10 >chr11 >chr12 >chr13 >chr14 >chr15 >chr16 >chr17 >chr18 >chr19 >chrX >chrY >chrM
它們的順序一致
當使用samtools或picard對SAM/BAM文件進行排序時,這些工具就會讀取頭信息,按照頭信息指定的順序來排chromosome/contig。所以進行排序時需要提供包含頭信息的SAM/BAM文件。
那么普通情況下我們的chromosome/contig排序情況是什么樣的?
一般情況下我們獲取參考基因組序列文件的來源有三個:
- NCBI
- ENSEMBEL
- UCSC Genome Browser
這里以UCSC FTP下載源為例:
這是一個壓縮文件,使用
tar zxvf chromFa.tar.gz
解壓后,會得到多個fasta文件,每條chromosome/contig一個fasta文件:chr1.fa, chr2.fa ...之后我們會將它們用
cat *.fa >ref.fa
合并成一個包含多條chromosome/contig的物種參考基因組序列文件用
grep ">" ref.fa
可以查看合并后發ref.fa文件中染色體的排列順序為:>chr10 >chr11 >chr12 >chr13 >chr14 >chr15 >chr16 >chr17 >chr18 >chr19 >chr1 >chr1_GL456210_random >chr1_GL456211_random >chr1_GL456212_random >chr1_GL456213_random >chr1_GL456221_random >chr2 >chr3 >chr4
這和我們平時想象的染色體的排列順序是不是有一些出入?難道不應該是從chr1開始到chr22,最后是chrX和chrY這樣的順序嗎?
想象歸想象,實際上它是按照字符順序進行的,chr11就應該排在chr2前面
一般情況下在進行SAM文件的排序時,染色體的排序到底是按照哪種規則進行排序的,不是一個很重要的問題,也不會對后續的分析產生影響,但是在執行GATK流程時,GATK對染色體的排序是有要求的,必須按照從chr1開始到chr22,最后是chrX和chrY這樣的順序,否則會報錯
面對這樣變態的要求,我們怎么解決?
在構造ref.fa文件時,讓它按照從chr1開始到chr22,最后是chrX和chrY這樣的順序進行組織就可以了:
for i in $(seq 1 22) X Y M;
do cat chr${i}.fa >> hg19.fasta;
done
2. SAM文件中FLAG值的理解
FLAG列在SAM文件的第二列,這是一個很重要的列,包含了很多mapping過程中的有用信息,但很多初學者在學習SAM文件格式的介紹時,遇到FLAG列的說明,常常會一頭霧水
what?還二進制,這也太反人類的設計了吧!
不過如果你站在開發者的角度去思考這個問題,就會豁然開朗
在mapping過程中,我們想記錄一條read的mapping的信息包括:
- 這條read是read1 (forward-read) 還是read2 (reverse-read)?
- 這條read比對上了嗎?與它對應的另一頭read比對上了嗎?
- ...
這些信息總結起來總共包括以下12項:
序號 | 簡寫 | 說明 |
---|---|---|
1 | PAIRED | paired-end (or multiple-segment) sequencing technology |
2 | PROPER_PAIR | each segment properly aligned according to the aligner |
3 | UNMAP | segment unmapped |
4 | MUNMAP | next segment in the template unmapped |
5 | REVERSE | SEQ is reverse complemented |
6 | MREVERSE | SEQ of the next segment in the template is reversed |
7 | READ1 | the first segment in the template |
8 | READ2 | the last segment in the template |
9 | SECONDARY | secondary alignment |
10 | QCFAIL | not passing quality controls |
11 | DUP | PCR or optical duplicate |
12 | SUPPLEMENTARY | supplementary alignment |
而每一項又只有兩種情況,是或否,那么我可以用一個12位的二進制數來記錄所有的信息,每一位表示某一項的情況,這就是原始FLAG信息的由來,但是二進制數適合給計算機看,不適合人看,需要轉換成對應的十進制數,也就有了我們在SAM文件中看到的FLAG值
但是FLAG值所包含信息的解讀還是要轉換為12位的二進制數
3. SAM文件中那些未比對的reads
SAM格式文件的第3和第7列,可以用來判斷某條reads是否比對成功到了基因組的染色體,左右兩條reads是否比對到同一條染色體
有兩個方法可以提取未比對成功的測序數據:
- SAM文件的第3列是*的(如果是PE數據,需要考慮第3,7列)
$ samtools view sample.bam | perl -alne '{print if $F[2] eq "*" or $F[6] eq "*" }' sample.unmapped.sam
- 或者SAM文件的flag標簽包含0x4的
# 小寫的f是提取,大寫的F是過濾 $ samtools view -f4 sample.bam sample.unmapped.sam
雖然上面兩個方法得到的結果是一模一樣的,但是這個perl腳本運行速度遠遠比不上上面的samtools自帶的參數
對于PE數據,在未比對成功的測序數據可以分成3類:
- 僅reads1沒有比對成功
該提取條件包括:
- 該read是read1,對應于二進制FLAG的第7位,該位取1,其十進制值為64;
- 該read未成功比對到參考基因組,對應于二進制FLAG的第3位,該位取1,其十進制值為4;
- 另一配對read成功比對到參考基因組,對應于二進制FLAG的第4位,該位取0,其十進制值為8;
# 對于取1的位點采用提取的策略,用-f參數,值設為64+4=68 # 對于取0的位點采取過濾的策略,用-F參數,值設為8 $ samtools view -u -f 68 -F 8 alignments.bam >read1_unmap.bam
- 僅reads2沒有比對成功
該提取條件包括:
- 該read是read2,對應于二進制FLAG的第8位,該位取1,其十進制值為128;
- 該read未成功比對到參考基因組,對應于二進制FLAG的第3位,該位取1,其十進制值為4;
- 另一配對read成功比對到參考基因組,對應于二進制FLAG的第4位,該位取0,其十進制值為8;
# 對于取1的位點采用提取的策略,用-f參數,值設為128+4=132 # 對于取0的位點采取過濾的策略,用-F參數,值設為8 $ samtools view -u -f 132 -F 8 alignments.bam >read2_unmap.bam
- 兩端reads都沒有比對成功
該提取條件包括:
- 該read未成功比對到參考基因組,對應于二進制FLAG的第3位,該位取1,其十進制值為4;
- 另一配對read未成功比對到參考基因組,對應于二進制FLAG的第4位,該位取1,其十進制值為8;
# 對于取1的位點采用提取的策略,用-f參數,值設為4+8=12 $ samtools view -u -f 12 alignments.bam >pairs_unmap.bam
看完這一部分,是不是有一個感覺:FLAG玩得溜,SAM文件可以處理得出神入化
4. 為什么一條read會有多條比對記錄?
首先,思考一個問題:對于PE數據,一條測序片段(fragment)有read1和read2兩條測序片段,它們倆的名字相同,那么對于這一條測序片段,對它進行mapping之后得到的SAM文件中會出現幾條記錄呢?
先聲明以下只對BWA比對得到的SAM文件進行討論,對其他比對工具輸出的SAM文件可能不適用
首先,基于經驗積累告訴我,它會得到有且只有兩條記錄,原因在于,BWA在對每條read執行比對時只會給出一個hit,若這條read是multiple mapping的情況,它會從中選擇MAPQ值最高的那個hit作為輸出,若存在多個hits的MAPQ值相等且最高,那么BWA會從中隨機選擇一個作為輸出
對于我的這個假設可以用以下的方法進行驗證:
# 將SAM文件的第一列提出來,排序去重,同時統計每個QNAME出現的次數
$ samtools view alignment.bam | cut -f1 | sort | uniq -c >record.count
得到的統計結果如下:
2 ERR144849.1
2 ERR144849.10
2 ERR144849.100
2 ERR144849.1000
2 ERR144849.10000
2 ERR144849.100000
2 ERR144849.1000000
2 ERR144849.10000000
2 ERR144849.10000001
2 ERR144849.10000002
2 ERR144849.10000003
2 ERR144849.10000004
2 ERR144849.10000005
...
上面的測試結果與我們的假設吻合
但是在一次處理三代測序數據(三代測序數據是Single-End)中發現了不同:
在輸出中出現了一些不太和諧的結果:有極少部分的QNAME對應2條以上的記錄,這意味著存在一條read會有多條比對記錄的情況,why?
對這個與預期不完全相符的結果,嘗試去尋找里面的原因,其間進行了各種各樣的推理、假設、驗證,最終在 李恒的github 中找到了答案
2. Why does a read appear multiple times in the output SAM?
BWA-SW and BWA-MEM perform local alignments. If there is a translocation, a gene fusion or a long deletion, a read bridging the break point may have two hits, occupying two lines in the SAM output. With the default setting of BWA-MEM, one and only one line is primary and is soft clipped; other lines are tagged with 0x800 SAM flag (supplementary alignment) and are hard clipped.
這種情況容易在三代測序數據中出現
5. 同一份BAM文件samtools depth和samtools mpileup的結果不同?
如果你用的是Single-End的數據,那么差異應該比較小,不會太明顯,而在Pair-End上差異可能會比較大,之所以會產生這些差異,原因有兩點:
(1)mpileup會默認將PE reads中比對情況異常的那些reads(包括雙端都比上,但是兩條配對reads之間的比對距離明顯偏離了插入片段的長度分布,或者一端比對上而另一端沒比對上)丟棄,則在計算depth時,這些被丟棄的reads不參與統計,而depth則不會,depth默認不做任何過濾
mpileup中提供了一個
-A
選項來保留異常比對的reads,如果設置了這個選項,那么在這點上mpileup的depth統計就和samtools depth相同了(2)從上圖的第二個紅框可以看出,在默認情況下,mpileup還會過濾掉測序質量值低于13的堿基,depth默認不過濾
從上面列出的兩點差異可以看出,mpileup默認輸出的是高質量的覆蓋深度,這是有歷史原因的:當場mpileup功能被開發出來就是為了與bcftools組合,將samtools mpileup的輸出作為bcftools的輸入用于下游的snp-calling,當然需要保證數據的質量
當然可以通過設置對應的參數使得它的屬于結果與depth的一致,但是不推薦這么做
6. 為什么samtools flagstat與hisat2的mapping rate不同?
下面是對同一個樣本的paired-end Fastaq文件比對結果(比對使用hisat2),hisat2和samtools分別給出的mapping rate的統計
hisat2:
39928651 reads; of these:
39928651 (100.00%) were paired; of these:
8439896 (21.14%) aligned concordantly 0 times
30158798 (75.53%) aligned concordantly exactly 1 time
1329957 (3.33%) aligned concordantly >1 times
----
8439896 pairs aligned concordantly 0 times; of these:
298072 (3.53%) aligned discordantly 1 time
----
8141824 pairs aligned 0 times concordantly or discordantly; of these:
16283648 mates make up the pairs; of these:
11658022 (71.59%) aligned 0 times
4210488 (25.86%) aligned exactly 1 time
415138 (2.55%) aligned >1 times
85.40% overall alignment rate
samtools flagstat:
85207970 + 0 in total (QC-passed reads + QC-failed reads)
5350668 + 0 secondary
0 + 0 supplementary
0 + 0 duplicates
73549948 + 0 mapped (86.32% : N/A)
79857302 + 0 paired in sequencing
39928651 + 0 read1
39928651 + 0 read2
62977510 + 0 properly paired (78.86% : N/A)
63902424 + 0 with itself and mate mapped
4296856 + 0 singletons (5.38% : N/A)
173078 + 0 with mate mapped to a different chr
127302 + 0 with mate mapped to a different chr (mapQ>=5)
從上面可以看出,hisat2給出的mapping rate為85.40%,而samtools給出的為86.32%,兩個的統計結果不一樣,而且samtools的統計會大一些,what?
介四什么鬼?
我們來簡單地分析一下:
hisat2中,
samtools中,
計算沒問題,那問題出在哪呢?
有沒有注意到上面的兩個式子中的分子和分母,計算它們的差值:
分子:
分母:
發現了沒有,它們的差值正好都等于samtools flagstat的輸出結果的第二行:
5350668 + 0 secondary
所以,hisat2和samtools計算mapping rate的公式實際上分別為:
hisat2
samtools
其中,recorder number表示SAM文件中除去頭信息部分的比對記錄數,每一行是一條比對記錄
一般來說,我們想得到的是hisat2計算公式所得到的統計結果,hisat2統計結果在比對結束后會以標準錯誤形式給出,我們可以將標準錯誤重定向到一個log文件中,但是如果我們忘了保持這個統計結果,怎么辦?
最簡單的辦法就是重新跑一遍hisat2,但是這樣太耗費時間和計算資源了,這時我們可以利用samtools flagstat對SAM文件的統計結果,以及它的部分統計值與hisat2計算公式的關系,快速地算出準確的mapping rate:
參考資料:
(1) 【簡書】從零開始完整學習全基因組測序數據分析:第5節 理解并操作BAM文件
(2) 【生信技能樹】【直播】我的基因組(十五):提取未比對的測序數據
(4) 【簡書】黃樹嘉《樣本量重要,還是測序深度重要? 生物信息工程師可以分為多少種類型? |《解螺旋技術交流圈》精華第3期》