經過了第四節的長文,我想大家基本上已經知道了一個WGS流程該如何構建起來了吧。但在那一節中限于篇幅有兩個很重要的文件我沒能展開來講,分別是:BAM和VCF文件。這篇我們先說BAM文件。
什么是BAM
BAM是目前基因數據分析中最通用的比對數據存儲格式,它既適合于短read也適合于長read,最長可以支持128Mbp的超大read!除了后綴是.bam之外,有些同學可能還會看到.cram,甚至.sam后綴的文件,其實它們一個是BAM的高壓縮格式(.cram)——IO效率比原來的BAM要略差;另一個是BAM的純文本格式(.sam)。當然格式都是一樣的,因此為了描述上的清晰,我下面都統一用BAM。
BAM文件格式
其實一開始它的名字是SAM(The Sequencing Alignment/Map Format的英文簡稱),第一次出現的時候,它是bwa比對軟件的標準輸出文件,但原生的SAM是純文本文件,十分巨大(比如:一個人30x全基因組測序的sam大小超過600G),非常容易導致存儲空間爆滿!為了解決這個問題,bwa的開發者李恒(lh3)設計了一種比gz更加高效的壓縮算法,對其進行壓縮,這就是我們所說的BAM,它的文件大小差不多只有原來的1/6。
在2007年,NGS技術剛剛興起之時,各類短序列比對軟件層出不窮,輸出格式也是各有特點,各家各有一套,并沒有什么真正的標準可言,可以說那是一個誰都說我最好的時期。
但逐漸的,研究者們發現BAM格式對Mapping信息的記錄是最全面的,用起來也是最靈活的。bwa的作者還為BAM文件開發了一個非常好用的工具包——Samtools,使得人們對BAM文件的處理變得十分便利,拓展性也變得非常強,后來還有類似于IGV等專門支持BAM的工具也越來越多,因此它就逐漸成為了主流。
現在基本上所有的比對數據都是用BAM格式存儲的,儼然已經成為了業內的默認標準。
在2013年,研究者們還專門將Samtools的處理核心剝離出來,并將其打包成為一個專門用于處理高通量數據的API——htslib,除了C語言版本之外還有Java和Python版本,這些在github上都能直接找到。后續許多與NGS數據處理有關的工具基本都會使用這個API進行相關功能的開發,可見其影響力。
ok,背景的介紹就先到此為止了,我們回歸主題。下面這個圖是我從一份剛剛完成比對的bam文件中截取出來的內容:
由于屏幕所限,無法把全部的內容都包含進來,特別是header信息,貼在這里僅是為了讓還沒見過BAM文件的同學們能夠對它有一個總體的感覺。
如果是SAM文件,同時你也熟悉linux操作的話,直接在linux終端用less打開即可(注意:不要試圖在本地使用文本編輯器,如vim等直接打開文件,會撐死機子的),但如果我們要查看的是BAM,那么必須通過Samtools(可以到samtools的網站下載并安裝)。
$ less -SN in.sam # 打開sam文件
$ samtools view -h in.bam # 打開bam文件
BAM文件分為兩個部分:header和record。這里額外說一句,許多NGS組學數據的存儲格式都是由header和record兩部分組成的。
以上例子,在samtools view中加上-h參數目的是為了同時把它的header輸出出來,如果沒有這個參數,那么header默認是不顯示的。
header內容不多,也不會太復雜,每一行都用‘@’ 符號開頭,里面主要包含了版本信息,序列比對的參考序列信息,如果是標準工具(bwa,bowtie,picard)生成的BAM,一般還會包含生成該份文件的參數信息(如上圖),@PG標簽開頭的那些這里需要重點提一下的是header中的@RG也就是Read group信息,這是在做后續數據分析時專門用于區分不同樣本的重要信息。它的重要性還體現在,如果原來樣本的測序深度比較深,一般會按照不同的lane分開比對,最后再合并在一起,那么這個時候你會在這個BAM文件中看到有多個RG,里面記錄了不同的lane,甚至測序文庫的信息,唯一不變的一定是SM的sample信息,這樣合并后才能正確處理。
其實,關于這一點我在上一篇文章中講序列比對時的也特意強調了這些方面,不記得的同學們也可以翻看上一篇的相關內容。
接下來重點要說的是BAM的核心:record(有時候也叫alignment section,即,比對信息)。這是我們通常所說的序列比對內容,每一行都是一條read比對信息,它的記錄看起來是這樣的:
我這里借用了網上的一張圖片來輔助說明,recoed中的每一個信息都是用制表符tab分開的。
下面我們就來仔細瞧瞧這里的每一個信息分別都是什么。
以上,前11列是所有BAM文件中都必須要有的信息,而且從描述中我們也能夠比較清楚地知道其所代表的含義。但其中,有幾個信息實在太重要了,以至于我認為有必要對其進行詳細說明。
第一,Flag信息
這是一個非常特別并且重要的數字,也是一個容易被忽視的數字,這可能和許多生信工程師也并不完全理解這個值有關。許多同學在第一次看到其官方文檔中的描述之后依然會覺得十分困惑,但它里面實際上記錄了許多有關read比對情況的信息。想要讀懂它的一個關鍵點是我們不能夠將其視為一個數字,而是必須將其轉換為一串由0和1組成的二進制碼,這一串二進制數中的每一個位(注意是“位”,bit的意思)都代表了一個特定信息,它一共有12位(以前只有8位),所以一般會用一個16位的整數來代表,這個整數的值就是12個0和1的組合計算得來的,因此它的數值范圍是0~2048(2的12次方,計算機科學的同學對這種計算應該不陌生)。
那么下面我就結合其文檔和自己的實踐經驗對這12個位的含義用更加通俗易懂的語言來重新描述,如下表:
所以,通過上面這個表的信息,我們就可以清楚地知道每一個FLAG中都包含了什么信息。比如看到FLAG = 77時,我們第一步要做的就是將其分解為二進制序列(也可以理解為分解成若干個2的n次方之和):
77 = 000001001101 = 1 + 4 + 8 +64,這樣就得到了這個FLAG包含的意思:PE read,read比對不上參考序列,它的配對read也同樣比不上參考序列,它是read1。
當然,如果你希望自己在程序中寫一段處理FLAG的代碼,那么顯然是不會像我們這個例子那樣去分解這個整數的,多麻煩啊!那么該如何做呢?其實也很簡單,比如我們要獲得其中某個位(假設第N位)的值——只需要將這個FLAG值和2的N次方做與的運算即可。在與運算時,FLAG值首先會被轉換成一串二進制序列(如77=000001001101),而2的N次方除了第N位是1之外,其它的都是0,“與”了之后其它信息就會被屏蔽掉。比如,我們想知道該read是否比對上了參考序列,那么只需要計算FLAG & 4 的值就行了,如果結果是1那么就是比對上了,如果是0則代表沒有比上。
不過,在實際工作中,除非遇到特殊的情況,否則我一般更推薦調用官方的htslib這個包來協助處理,它是一個C語言庫,如果你用Python,則是pysam——htslib的python包(Java則是htsjdk),包中已經幫我們做了這些處理,可以直接得到結果,下一篇文章里我會用pysam舉例說明如何用它來操作bam文件。
另外,下面這一段代碼是htslib(samtools的核心庫)中定義的12個與flag值進行與操作獲取對應位信息的變量,感興趣的同學可以再htslib里面的sam.h文件中找到,在做一些需要觸達基礎性原理的開發時或許你會用到。
/*! @abstract the read is paired in sequencing, no matter whether it is mapped in a pair */
#define BAM_FPAIRED 1
/*! @abstract the read is mapped in a proper pair */
#define BAM_FPROPER_PAIR 2
/*! @abstract the read itself is unmapped; conflictive with BAM_FPROPER_PAIR */
#define BAM_FUNMAP 4
/*! @abstract the mate is unmapped */
#define BAM_FMUNMAP 8
/*! @abstract the read is mapped to the reverse strand */
#define BAM_FREVERSE 16
/*! @abstract the mate is mapped to the reverse strand */
#define BAM_FMREVERSE 32
/*! @abstract this is read1 */
#define BAM_FREAD1 64
/*! @abstract this is read2 */
#define BAM_FREAD2 128
/*! @abstract not primary alignment */
#define BAM_FSECONDARY 256
/*! @abstract QC failure */
#define BAM_FQCFAIL 512
/*! @abstract optical or PCR duplicate */
#define BAM_FDUP 1024
/*! @abstract supplementary alignment */
#define BAM_FSUPPLEMENTARY 2048
第二,CIGAR
CIGAR是C
ompactI
diosyncraticG
appedA
lignmentR
eport的首字母縮寫,稱為“雪茄”字符串。
作為一個字符串,它用數字和幾個字符的組合形象記錄了read比對到參考序列上的細節情況,讀起來要比FLAG直觀友好許多,只是記錄的是不同的信息。比如,一條150bp長的read比對到基因組之后,假如看到它的CIGAR字符串為:33S117M,其意思是說在比對的時候這條read開頭的33bp在被跳過了(S),緊接其后的117bp則比對上了參考序列(M)。這里的S代表軟跳過(Soft clip),M代表匹配(Match)。CIGAR的標記字符有“MIDNSHP=XB”這10個,分別代表read比對時的不同情況:
除了最后‘=XB’非常少見之外,其它的標記符通常都會在實際的BAM文件中碰到。另外,對于M還是再強調一次,CIGAR中的M,不能覺得它代表的是匹配就以為是百分百沒有任何miss-match,這是不對的,多態性堿基或者單堿基錯配也是用M標記!
第三,MAPQ,比對質量值
這個值同樣非常重要,它告訴我們的是這個read比對到參考序列上這個位置的可靠程度,用錯誤比對到該位置的概率值(轉化為Phred scale)來描述:-10logP{錯比概率}。因此MAPQ(mapping quality)值大于30就意味著錯比概率低于0.001(千分之一),這個值也是我們衡量read比對質量的一個重要因子。
剩下的幾列在上面的格式表中描述的也比較清楚,基本沒有過于隱藏的信息,因此我就不打算再一一細說了,如果大家依然有困惑可以到后臺留言。
此外,細心的同學可能也已經發現了:fastq的所有信息都被涵蓋到了BAM文件中了,包括比對不上的read也在,因此獲得了BAM其實也等于獲得了所有的read。而且,fastq有時也會被轉換成一種uBam文件,指的就是un-mapping BAM——沒有做過比對的BAM文件。它相比于Fastq可以用metadata存儲更多有用的信息,不過這不是我們這篇文章想說的內容。
最后,還是再說明一次:BAM文件中除了必須的前11列信息之外,不同的BAM文件中后面記錄metadata的列是不固定的,在不同的處理軟件中輸出時也會有所不同,我們也可以依據實際的情況增刪不同的metadata信息。
使用samtools view查看BAM文件
BAM文件由于是特殊的二進制格式,因此沒辦法通過文本的形式直接打開,要用samtools的view功能在終端上進行查看(上文也已經說到這里在進行系統補充),如:
$ samtools view in.bam
如果不想從頭開始看,希望快速地跳轉到基因組的其它位置上,比如chr22染色體,那么可以先用samtools index生成BAM文件的索引(如果已經有索引文件則不需該步驟),然后這樣操作:
$ samtools index in.bam # 生成in.bam的索引文件in.bam.bai
$ samtools view in.bam chr22 # 跳轉到chr22染色體
$ samtools view in.bam chr22:16050103 # 跳轉到chr22:16050103位置
$ samtools view in.bam chr22:16050103-16050103 # 只查看該位置
IGV或者samtools tview查看比對情況
以上,我基本上列舉了我們會在終端上如何查看BAM文件的幾個最常用操作。但如果你想更直觀查看的BAM文件,IGV是目前最好的一個選擇,但僅適合于文件還比較小的情況,效果如下:
如果你的BAM文件很大,都超過了你的本地電腦磁盤了,你還是想看該怎么辦?你有兩個選擇:
第一,把你想查看的那部分區域用samtools view提取出來,生成一份小一些的BAM,然后下載下來,在導入到IGV中。
$ samtools view -h in.bam chr22:16050103-16050203 | samtools view -Sb - > small.bam
第二,不下載,直接在終端用samtools tview進行查看。samtools tview有類似于IGV的功能,雖然體驗會稍差一些。
$ samtools tview --reference hg38.fa in.bam
在該模式下,按下鍵盤‘g’后,會跳出一個Goto框,在里面輸入想要調整過去的位置,就行了,比如:
按下esc鍵則可以取消。另外,為了節省空間,加快查詢效率,read中與參考序列相同的部分被用一串串不同顏色的點表示,只留下miss-match的堿基和發生indel變異的區域。其中圓點表示正鏈比對,逗號表示負鏈比對。不同的顏色代表不同的比對質量值:白色>=30,黃色20-29,綠色10-19,藍色0-9。如果你還想知道的其他的功能,可以在tview模式里按下“?”問號,就會彈出類似下面這樣的幫助窗口,然后按照指引做就行了。
雖然看起來不如IGV體驗那樣好,功能也比較單一(僅可以查看比對情況),但可貴之處在于可以在終端里面直接操作,當需要快速查看某個位置的比對情況時,操作效率非常高。而如果要退出該模式,也非常簡單,按下q鍵就可以了。
小結
那么,有關BAM格式的內容我們就暫且先到這里吧,大家如果有疑惑或者感興趣的內容都可以到后臺留言,我都會定時進行回復。在下一篇文章中,我們將重點介紹如何使用pysam來操作bam文件了。