DNA配列を含むgzip圧縮されたDNAfastaファイル内のDNAトリヌクレオチドを繰り返しカウントするgrepループを作成しました。
declare -a tri=(AAA AAC AAG AAT CAA .. etc)
for i in ${tri[@]}
do
gzip -cd gencode.v18.pc_transcripts.fa.gz | grep -v "^>" | grep -o $i | wc -l
done
Fastaファイルがこの形式である場合(はるかに大きいですが)
head test.fa
>id1
TTTTTAAAAA
>id2
GGGGGCCCCC
etc..
これは機能しますが(つまり、各トリヌクレオチドの発生をカウントします)、データを64回(可能なトリヌクレオチドごとに1回)通過する必要があるため、非常に非効率的です。
私の質問は、bash
またはgrep
を使用して、ファイルの1回のパスで各トリヌクレオチドをカウントする方法がありますか(ファイルが非常に大きいため)?
どうも
IFS=$'\n'
gzip -dc file.gz | grep -v '^>' | grep -Foe "${tri[*]}" | sort | uniq -c
ちなみに、AAAC
はAAA
とAAC
の両方に一致しますが、grep -o
はそのうちの1つだけを出力します。それはあなたが望むものですか?また、AAA
でのAAAAAA
の出現回数は? 2または4([AAA]AAA
、A[AAA]AA
、AA[AAA]A
、AAA[AAA]
)?
多分あなたは代わりに欲しい:
gzip -dc file.gz | grep -v '^>' | fold -w3 | grep -Fxe "${tri[*]}" | sort | uniq -c
これは、行を3文字のグループに分割し、出現回数を完全な行としてカウントします(AAA
でACAAATTCG
の出現回数を0回検出します(これはACA AAT TCG
))。
またはその一方で:
gzip -dc file.gz | awk '
BEGIN{n=ARGC;ARGC=0}
!/^>/ {l = length - 2; for (i = 1; i <= l; i++) a[substr($0,i,3)]++}
END{for (i=1;i<n;i++) printf "%s: %d\n", ARGV[i], a[ARGV[i]]}' "${tri[@]}"
(AAA
でAAAAAA
が4回出現します)。
@stéphane-chazelasの2番目の例は素晴らしいですが、sort
コマンドは、データが大きくなるにつれてこれを実際に遅くする可能性があります。
非ヘッダー行の文字が有効なヌクレオチドであると想定できますか?これにより、tri
の一致が削除されます。
gzip -dc file.gz | grep -v '^>' | fold -w3 | awk '{a[$0]++} END{for(codon in a) {printf "%s: %d\n", codon, a[codon]}'
関連する注記として、3ヌクレオチドトークンを2バイトの8進数(またはそこから2進数)に変換すると、データストリームのサイズが2/3または1/3減少します。
gzip -dc file.gz | grep -v '^>' | tr ACGT 0123 | fold -w3 | cat <(echo "obase=8; ibase=4;" ) - | bc | xargs printf "%02d\n" | tee foo.octal | xxd -r -p > foo.bin
ヌクレオチドに戻る
cat foo.bin | xxd -p | fold -w2 | cat <(echo "obase=4; ibase=8;") - | bc | xargs printf "%03d" | tr 0123 ACGT
xargsはおそらくここでの制限ステップであり、おそらく一度にN行を解析することでそれを修正するか、gnuparallelを使用するでしょう。