[英]How can we compress DNA string efficiently
DNA串可以是任何長度,包括5個字母(A,T,G,C,N)的任何組合。
什么是壓縮包含5個字母(A,T,G,C,N)的字母表的DNA串的有效方法。 我們可以使用較少的位來有效地壓縮和檢索,而不是考慮每個字母3位。 任何人都可以建議一個有效壓縮和檢索的偽代碼嗎?
如果你願意(a)每個字符都有不同的位大小,你可以(b)你總是從頭開始閱讀,而不是從中間閱讀。 那么,你可以得到類似的代碼:
從左到右閱讀,您只能以一種方式將比特流分成字符。 您一次讀取2位,如果它們是“11”,您需要再讀一位以了解它是什么字符。
注意:
我不太了解DNA,但是如果chars的概率不相等(每個意味着20%)。 你應該將最短的代碼分配給那些概率較高的代碼。
您有5個唯一值,因此您需要base-5編碼(例如A = 0,T = 1,G = 2,C = 3,N = 4)。
在32位中,您可以使log 5 (2 32 )= 13 base-5值。
在64位中,您可以使log 5 (2 64 )= 27 base-5值。
編碼過程將是:
uint8_t *input = /* base-5 encoded DNA letters */;
uint64_t packed = 0;
for (int i = 0; i < 27; ++i) {
packed = packed * 5 + *input++;
}
並解碼:
uint8_t *output = /* allocate buffer */;
uint64_t packed = /* next encoded chunk */;
for (int i = 0; i < 27; ++i) {
*output++ = packed % 5;
packed /= 5;
}
有很多方法可以壓縮,但主要問題是你要壓縮哪些數據? 1.來自測序儀的原始未對齊序列數據(fastq)2。對齊數據(sam / bam / cram)3。參考基因組
我們可以結合使用Roee Gavirel的想法和以下內容來獲得更加緊湊的結果。 由於Roee的想法仍然規定我們的五個字符中的兩個字符被映射到一個3位字,序列的部分中至少有五個字符中的一個沒有出現但是一個3位字可以映射到2比特話,減少我們的最終結果。
切換映射的條件是,如果存在一個部分,其中五個字符中的至少一個沒有出現,並且其中一個3位字只出現一次,超過我們的部分前綴長度的兩倍。 如果我們訂購可能的字符(例如,按字母順序排列),給定三個位表示特定的缺失字符(如果有多個缺失,我們選擇第一個按順序)或沒有缺失,我們可以立即分配一致的2位映射對於其他四個字符。
我們的前綴有兩個想法:
(1)
3位:缺少的字符(如果沒有,我們使用Roee的編碼作為該部分);
x位:表示段長度的常數位。 對於65000的最大長度部分,我們可以指定x = 16。
為了證明前綴使用的合理性,我們需要一個部分,其中五個字符中的一個不出現,而一個3位字出現39次或更多。
(2)
3位:缺少的字符(如果沒有,我們使用Roee的編碼作為該部分);
x位:前綴下一部分的位數 - 取決於最長部分的字符數。 x = 6意味着最大截面長度可能是2 ^(2 ^ 6)! 不太可能。 對於65000的最大長度部分,我們可以指定x = 4;
前綴前一部分中指示的位數,表示當前節長度。
在上面的示例中,我們的前綴長度可以在11到23位之間變化,這意味着為了證明它的使用,我們需要一個部分,其中五個字符中的一個不出現,而一個3位字出現在它們之間23至47次或更多次。
坦率地說,我將從一些版本的Lempel-Ziv壓縮開始(一類包含通用gzip
壓縮格式的壓縮算法)。 我注意到一些評論說通用壓縮算法在原始基因組數據上不能很好地工作,但它們的有效性取決於數據如何呈現給它們。
請注意,大多數通用壓縮程序(如gzip
)基於每個字節檢查其輸入。 這意味着以3位/鹼基“預壓縮”基因組數據會適得其反 ; 相反,在通過通用壓縮器運行之前,您應該將每個鹼基一個字節的未壓縮基因組數據格式化。 Ascii“AGTCN”編碼應該沒問題,只要您不通過包含空格,換行符或大小寫的變化來添加噪聲。
Lempel-Ziv壓縮方法通過識別輸入中的重復子串,然后通過參考前面的數據對它們進行編碼來工作; 我希望這類方法能夠在適當呈現的基因組數據上做得相當不錯。 一種更具基因組特異性的壓縮方法可能會對此有所改進,但除非我對基因組編碼有一些強烈的,非局部的限制,否則我不會期望有重大改進。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.