# RefSeq転写産物の3'UTRの範囲をBEDに書き出す ### 目的 * GGGenomeでRefSeq転写産物の3'UTRを検索したい。 * GGGenomeは検索結果をBED形式で出力できるので、3'UTRの範囲を記載したBEDファイルを用意しておけば、`bedtools intersect` で3'UTRに対するヒットのみを得ることができる。 ### RefSeq転写産物のgbffを入手 ftp://ftp.ncbi.nlm.nih.gov/refseq/release/complete/ から `complete.*.rna.gbff.gz` をダウンロード。 * `complete` は全生物種を含む * `rna` が転写産物(ほかに `genomic`, `protein` がある) * `gbff` はGenBank形式(配列+アノテーション) RefSeq 215 では、圧縮された状態で合計 71GB ある。 ### gbffのパースの準備 #### コマンド ``` zcat complete.*.rna.gbff.gz \ | egrep '^(LOCUS|VERSION|SOURCE|\s+CDS|//)' \ ``` (メモ)gbffは大きいため、最初に `egrep` で必要な行だけを抜き出すことにより処理の時間を短縮。行末の `\` に続けて下記コマンドを順次実行。 ``` | perl -ne 'BEGIN{ $/ = "\n//\n" } my $length = /^LOCUS\ .*?(\d+)\ *bp/m ? $1 : "" ; my $version = /^VERSION\ +(\S*)/m ? $1 : "" ; my $source = /^SOURCE\ +(.*?)\ *$/m ? $1 : "" ; my ($cds1, $cds2) = /^\ {5}CDS\ +(\d+)\.\.(\d+)/m ? ($1, $2) : () ; print $source . "\t" . $version . "\t" . $cds1 . "\t" . $cds2 . "\t" . $length . "\n"' \ ``` (メモ)gbffでは各エントリが `//` で区切られているので、perlの行セパレータを `//` に変更して、1エントリをまるごと「1行」として読み込んで高速化。1エントリごとに、配列の長さ、生物種、version、CDS の start と end を抽出していく。 ``` | grep '^Homo sapiens (human)' \ | cut -f 2- \ ``` (メモ)ヒト `Homo sapiens (human)` のみ抽出。 ``` | grep -v '^X' ``` (メモ)predictedな転写産物 `XM_`, `XR_` を除外。 #### パースの途中の状態 gbff から必要な行だけ抜き出したもの。 ``` LOCUS NM_001387374 4051 bp mRNA linear PRI 21-APR-2022 VERSION NM_001387374.1 SOURCE Homo sapiens (human) CDS 167..2026 // LOCUS NM_001387375 4027 bp mRNA linear PRI 21-APR-2022 VERSION NM_001387375.1 SOURCE Homo sapiens (human) CDS 167..2002 // LOCUS NM_001387376 3973 bp mRNA linear PRI 21-APR-2022 VERSION NM_001387376.1 SOURCE Homo sapiens (human) CDS 167..1948 // [...] ``` 最終的な出力。 ``` NM_001387562.1 221 2017 4790 NM_001387563.1 221 1219 1358 NR_073515.3 1315 NR_170667.1 6439 NR_047672.2 488 NR_038873.1 2636 NM_001141920.2 236 781 2901 NM_001363651.3 171 1949 2081 NM_001365041.3 510 1526 3569 NM_175569.3 236 778 2898 NM_001367912.2 39 1844 1986 NM_001387759.1 243 2255 2923 NM_001387772.1 160 2079 2747 [...] ``` BED形式のように見えるが開始位置が 0-based start でない点には注意。 `NM_` で始まるものは mRNA なので CDS の記載あり。 `NR_` で始まるものは ncRNA なので CDS の記載なし。 #### (2023/08/22追記) OAZ1, OAZ2, OAZ3, PEG10 遺伝子は ribosomal frameshift が起こるため、 ``` CDS join(480..1436,1436..2605) ``` のように記載されている。そのような場合にも対応できるよう下記のように修正。 ``` | perl -ne 'BEGIN{ $/ = "\n//\n" } my $length = /^LOCUS\ .*?(\d+)\ *bp/m ? $1 : "" ; my $version = /^VERSION\ +(\S*)/m ? $1 : "" ; my $source = /^SOURCE\ +(.*?)\ *$/m ? $1 : "" ; my ($cds1, $cds2) = /^\ {5}CDS\ +(\d+)\.\.(\d+)/m ? ($1, $2) : /^\ {5}CDS\ +join\((\d+)\.\.\d+,\d+\.\.(\d+)\)/m ? ($1, $2) : () ; print $source . "\t" . $version . "\t" . $cds1 . "\t" . $cds2 . "\t" . $length . "\n"' \ ``` ### (並列化) そのまま実行すると時間がかかるため、並列化する方法もメモ。 下記を `/tmp/parse.sh` に保存して `chmod 755` しておく。 ``` egrep '^(LOCUS|VERSION|SOURCE|\s+CDS|//)' \ | perl -ne 'BEGIN{ $/ = "\n//\n" } my $length = /^LOCUS\ .*?(\d+)\ *bp/m ? $1 : "" ; my $version = /^VERSION\ +(\S*)/m ? $1 : "" ; my $source = /^SOURCE\ +(.*?)\ *$/m ? $1 : "" ; my ($cds1, $cds2) = /^\ {5}CDS\ +(\d+)\.\.(\d+)/m ? ($1, $2) : /^\ {5}CDS\ +join\((\d+)\.\.\d+,\d+\.\.(\d+)\)/m ? ($1, $2) : () ; print $source . "\t" . $version . "\t" . $cds1 . "\t" . $cds2 . "\t" . $length . "\n"' \ | grep '^Homo sapiens (human)' \ | cut -f 2- \ | grep -v '^X' ``` 下記を実行。 ``` /bin/ls *gbff* \ | awk '{print "zcat "$1" | /tmp/parse.sh > /tmp/refseq215/"$1".txt" }' \ | /backup/bin/parallel.pl -12 ``` (メモ)[parallel.pl](https://github.com/meso-cacase/parallel/blob/master/parallel.pl) は並列化を支援する自作スクリプト。 終了したら、 ``` setopt numeric_glob_sort cat /tmp/refseq215/* > /tmp/hs_refseq215_cds.txt ``` でマージ完了。 ### 3'UTRの範囲の抽出 → BED化 * CDS end の値をそのまま 3'UTR start とする。 * 0-based start のBEDにするため。 * length の値を 3'UTR end とする。 * 出力の対象を mRNA `MN_` のみとする。 `/tmp/parse.sh` を下記のように修正して同様に実行。 ``` egrep '^(LOCUS|VERSION|SOURCE|\s+CDS|//)' \ | perl -ne 'BEGIN{ $/ = "\n//\n" } my $length = /^LOCUS\ .*?(\d+)\ *bp/m ? $1 : "" ; my $version = /^VERSION\ +(\S*)/m ? $1 : "" ; my $source = /^SOURCE\ +(.*?)\ *$/m ? $1 : "" ; my ($cds1, $cds2) = /^\ {5}CDS\ +(\d+)\.\.(\d+)/m ? ($1, $2) : /^\ {5}CDS\ +join\((\d+)\.\.\d+,\d+\.\.(\d+)\)/m ? ($1, $2) : () ; print $source . "\t" . $version . "\t" . $cds2 . "\t" . $length . "\n"' \ | grep '^Homo sapiens (human)' \ | cut -f 2- \ | grep '^NM_' ``` ``` /bin/ls *gbff* \ | awk '{print "zcat "$1" | /tmp/parse.sh > /tmp/refseq215/"$1".txt" }' \ | /backup/bin/parallel.pl -12 ``` 並列処理が終了したら、 ``` cat /tmp/refseq215/* \ | /backup/bin/sort_refseq_id.pl \ > /tmp/hs_refseq215_3utr.bed ``` でマージ完了。 (メモ)[sort_refseq_id.pl](https://gist.github.com/meso-cacase/7a287171a6b364b5b487bdb55c66b251) はテキストを RefSeq ID の順番にソートする自作スクリプト。 ### 結果 [hs_refseq215_3utr.bed](https://gist.github.com/meso-cacase/97301382511db5e5dd61366991dda8d7) (66,326行) ``` NM_000014.6 4495 4610 NM_000015.3 943 1285 NM_000016.6 1345 2261 NM_000017.4 1299 1859 NM_000018.4 2015 2184 [...] ``` * BED形式なので 0-based start である点に注意。 * CDSしか登録されていないエントリがある。 * その場合は start = end になっている。 ### 完了