以前下のような記事を書きましたが、もう少し効率よく求めることができそうなので、高速化してみようと思います。
目次
従来の方法
従来の方法では連続したヌクレオチドを3つずつ選択して、逐一翻訳しながら3パターン分やるというちょっと非効率な方法でアルゴリズムを書いていました。
さらに、終止コドンに当たった際は一旦終始コドンまでのアミノ酸配列を格納してから、翻訳を再開していたので処理が多くなってしまっていました。
そこで今回は、できる限りスマートにORFを抽出してみたいと思います。
作戦
ORFをスマートに抽出する作戦は以下の通りです。
1.ターゲットのmRNAを全域スキャンした後、先頭の1文字を取り除きます。
これを2回繰り返すことで、mRNAに存在する全てのコドンパターンを網羅したことになります。
2.1で取得した3つのアミノ酸配列(終止コドン込み)を終止コドンをマーカーとして切り出します。Biopythonを使用した場合、マーカーはアスタリスク(*)となります。
3.ターミナルに出力して完了です。
アルゴリズム
今回は関数を2つ作成してアプローチしていきます。
Biopythonモジュールをインポートし、seqに対象の配列(DNA)を代入します。
from Bio.Seq import Seq
seq = '''GGCGTCCTTTTCCGGTAAACGTCGGCCCATCACGAGCCTCTTGACCATATATGCTCATGT
GGCCCTCATTCTGTATATACGAGTGACAAATGTAGAGCGGATGCAAGGAACAGAGTAATA
TACCAAGAGCCACCCACGAGGTTCACTCCAAAGACAAGATGGAGACACTGTCTGATGAGA
GGCCAGCCGTCCCTAGCTCTGGGGTCAAAACAGAAGCGGCGGGTACCGCGCTAGACCCGC
TTCATAAGTCCCCACTGATGGTCAGGAATTGAGGGACGGATCCATGCATTCATCTCTCGC
TCGTTCTCAAAGGCCGCCGAGACACGAGGGGACCGAACGTGTCGGGACCTTGTGTGTCGG
CCTTGACGGAGCCTCGGCACCCGTCCATATCACCGGGACTCTTCCACTAGCTATGCTGGT
ACGACAGCCCTACGCTTCAGTGTAGCTACACTGAAGCGTAGGGCTGTCGTACCAGCATTG
CGCCGGCTCACGGAATGGATACCTAAGATCACGAGTACTGTCCCCTCTGCCCGTCCGACG
GATGATGACATTGAAGTCGGAGGTGGCCCAATAAGAGGCACGTCATACTAATACGAACGA
TTGAAACAAAGACAGACCGGTAGTTTAATTAACAGGCTTCGGCCCTAGTCTTCTCCTACA
AGCGTACGTTTATATCTTATACGCTTCCTTAGTCCGGCCCGCGTTAGCCGCGCAAGCTTA
GCGCCTAGTGATAATGGACTAAAGTGTATATGGGTCCATGGGTCCCGATTATGCACAGTT
AATACGCGTCCATAGAGGGGGATGTATATGGATTTACGCATAAGACCCATGTCTTGTCGA
CGCCACTCCGCAAATGTTCGATCCCCCCTACTCCGTGATATGAGTCAGCA'''次に関数get_orfcandidatesを作成します。
この関数は、第一引数として与えられたDNA配列を終止コドンを無視して3パターン強制的に翻訳し、candidates(ORFの候補)を返り値とします。
def get_orfcandidates(seq_raw):
candidates = []
for i in range(3):
seq_i = Seq(seq_raw).transcribe()[i:].replace('\n','').replace(' ','')
if len(seq_i)%3 == 1:
seq_i = seq_i[:-1]
elif len(seq_i)%3 == 2:
seq_i = seq_i[:-2]
else:
pass
candidates.append(seq_i.translate())
return candidates次にメインの関数である、get_orfsを作成します。
この関数は、candidatesの配列を開始”M”と終了”*”をマーカーとしてORFを切り出します。
そのため、get_orfcandidatesとget_orfsは直接連動して動きます。
def get_orfs(seq):
ORFs,M_index = [],[nucleotide for nucleotide in range(len(seq)) if seq[nucleotide]=='M']
for i in range(len(M_index)):
orf = ''
s_l= M_index[i]
for j in range(len(seq)-s_l):
if seq[j+s_l] != '*':
orf += str(seq[j+s_l])
elif seq[j+s_l] == '*':
ORFs.append(orf)
break
else:
pass
return(ORFs)処理の実行
空のリストorfsを作成し、処理後のORFを入れていきます。
この際、リバースコンプリメント(逆相補鎖)も考慮します。
import time
start = time.time()
orfs = []
seq = Seq(seq)
if __name__ == '__main__':
for i in range(3):
orf = get_orfs(get_orfcandidates(seq)[i])
orf_r = get_orfs(get_orfcandidates(seq.reverse_complement())[i])
if orf != [] or orf_r != []:
orfs += orf
orfs += orf_rここで、orfsの中には”被り”が存在するので、setを使用して重複を削除します。
orfs = list(set(orfs))最後にORFを全てターミナルに出力します。
print('-----------------------------------------')
for orf in orfs:
print(off)
process_time = time.time() - start
print(process_time)以上でターミナルに全ORFを表示させることができました。
実行結果
今回は904個のヌクレオチドからのORFの取得でしたが、掛かった時間は0.003秒でした。
以下に取得したORFを示します。
MWPSFCIYE
MDT
MFDPPYSVI
MRAT
MDGCRGSVKADTQGPDTFGPLVSRRPLRTSER
MGPDYAQLIRVHRGGCIWIYA
MVRN
MQGTE
MGPWVPIMHS
MLMWPSFCIYE
MDAY
MTCLLLGHLRLQCHHPSDGQRGQYS
MHSSLARSQRPPRHEGTERVGTLCVGLDGASAPVHITGTLPLAMLVRQPYASV
M
MDPYTL
MNAWIRPSIPDHQWGLMKRV
MSSSVGRAEGTVLVILGIHSVSRRNAGTTALRFSVATLKRRAVVPA
MKRV
MMTLKSEVAQ
MDPSLNS
MRKSIYIPLYGRVLTVHNRDPWTHIHFSPLSLGAKLARLTRAGLRKRIRYKRTLVGED
MHS
MLVRQPYASV
MGLMRKSIYIPLYGRVLTVHNRDPWTHIHFSPLSLGAKLARLTRAGLRKRIRYKRTLVGED
MD
MTLKSEVAQ
METLSDERPAVPSSGVKTEAAGTALDPLHKSPLMVRN
MRGQPSLALGSKQKRRVPR
MHGSVPQFLTISGDL
process time(s):
0.0030770301818847656
DNA_length = 904前回の冗長なORF取得アルゴリズムに比べてかなり高速に仕上げることができたと思います。


[…] ORFをもっと効率よく求めてみる 以前下のような記事を書きましたが、もう… […]