昨日、私は最初の答えを書きました。
それから私は ATOzTOA の答えを読みました。彼は非常に良いアイデアを持っていました: 肯定的な後読みアサーションを使用します。
私の答えは完全に外れていて、彼の考えは正しい方法だと思いました。
しかし、後で ATOzTOA のコードに欠陥があることに気付きました。
'ATGxzyxyzyyxyATGxzxzyxyzxxzzxzyzyxyzTGA'
検査された文字列に部分があるとします。肯定的な一致が発生し'xzyxyzyyxyATGxzxzyxyzxxzzxzyzyxyzTGA'
、前の部分で積極的な一致が発生する'ATG'
ため、その部分が一致を構成します。それで大丈夫です。
しかし、これは、この一致の直後に正規表現モーターがこの部分の最後に配置されることを意味し 'xzyxyzyyxyATGxzxzyxyzxxzzxzyzyxyzTGA'
ます。
そのため、正規表現モーターが次の一致を検索するとき、'ATG'
この部分の現在から始まる一致は見つかりません。これは、それよりずっと後の位置から再び実行されるためです。
.
したがって、質問に必要なものを達成する唯一の方法は、実際に私が書いた最初のアルゴリズムであり、それを再投稿します。
仕事は関数find_ORF_seq()によって行われます
関数True
の 2 番目のパラメーターに 2 番目の引数として渡すと、アルゴリズムを理解するのに役立つメッセージが出力されます。
そうでない場合、パラメーターはデフォルト値を取りますmessages
find_ORF_seq()
messages
None
パターンは'(atg).+?(?:TAA|TGA|TAG)'
大文字と小文字で書かれていますが、それは大文字と小文字の相対的な部分が正しくキャッチされる理由ではありません。後でわかるように、フラグre.IGNORECASE
が使用されているためです。一致する部分(?:TAA|TGA|TAG)
が大文字の部分だけでなく小文字の部分にも含まれる可能性があるため、このフラグが必要です。
アルゴリズムの本質は while ループにあります。これは、上記で説明したように、調査した部分が重複する可能性があるため必要です (私が正しく理解し、あなたが提供したサンプルと説明が正しい限り) . したがって、 or
を使用する可能性はなく、ループを実行します。 findall()
finditer()
fdnaシーケンスを次々と繰り返すのを避けるために、文字列内ma.start()
の一致の開始位置を与えるメソッドを使用し、 with ( +1ma
の値をインクリメントして、その時点で再度検索を開始しないようにします。見つかった一致の開始!)s
s = s + p + 1
私のアルゴリズムは、start_positions
後読みアサーションを使用せず、最初の 3 文字での実際の一致を使用するため、 の情報を必要としません: 一致の開始が大文字の部分にある場合、一致は制約に適合しないと宣言されます。それがma.group(1)
最初の3つの塩基をキャッチするとき('ATG'
または'atg'
正規表現がケースを無視するため)が等しいと言う'ATG'
検索する部分の間隔が 3 塩基の倍数になっていないように見えるので、s = s + p + 1
代わりにを入れざるを得ませんでした。s = s + p + 3
import re
sequence_list = ['atgttttgatgATGTTTTGATTT',
'atggggtagatggggATGGGGTGA',
'atgaaataatggggATGAAATAA',
'aaggtacttctcggctaACTTTTTCCAAGT']
pat = '(atg).+?(?:TAA|TGA|TAG)'
reg = re.compile(pat,re.IGNORECASE)
def find_ORF_seq(fdna,messages=None,s=0,reg=reg):
ORF_sequences = []
if messages:
print 's before == ',s
while True:
if messages:
print ('---------------------------\n'
's == %d\n'
'fdna[%d:] == %r' % (s,s,fdna[s:]))
ma = reg.search(fdna[s:])
if messages:
print 'reg.search(fdna[%d:]) == %r' % (s,ma)
if ma:
if messages:
print ('ma.group() == %r\n'
'ma.group(1) == %r'
% (ma.group(),ma.group(1)))
if ma.group(1)=='ATG':
if messages:
print "ma.group(1) is uppercased 'ATG' then I break"
break
else:
ORF_sequences.append(ma.group().upper())
p = ma.start()
if messages:
print (' The match is at position p == %d in fdna[%d:]\n'
' and at position s + p == %d + %d == %d in fdna\n'
' then I put s = s + p + 1 == %d'
% (p,s, s,p,s+p, s+p+1))
s = s + p + 1
else:
break
if messages:
print '\n==== RESULT ======\n'
return ORF_sequences
for fdna in sequence_list:
print ('\n============================================')
print ('fdna == %s\n'
'ORF_sequences == %r'
% (fdna, find_ORF_seq(fdna,True)))
###############################
print '\n\n\n######################\n\ninput sample'
fdna = 'atgttttgatggATGTTTGATTTATTTTAG'
print ' fdna == %s' % fdna
print ' **atgttttga**tggATGTTTGATTTATTTTAG'
print ' atgttttg**atggATGTTTGA**TTTATTTTAG'
print 'output sample'
print " ORF_sequences = ['ATGTTTTGA','ATGGATGTTTGA']"
print '\nfind_ORF_seq(fdna) ==',find_ORF_seq(fdna)
.
print
アルゴリズムをよりよく理解するための指示のない同じ関数。
import re
pat = '(atg).+?(?:TAA|TGA|TAG)'
reg = re.compile(pat,re.IGNORECASE)
def find_ORF_seq(fdna,messages=None,s =0,reg=reg):
ORF_sequences = []
while True:
ma = reg.search(fdna[s:])
if ma:
if ma.group(1)=='ATG':
break
else:
ORF_sequences.append(ma.group().upper())
s = s + ma.start() + 1
else:
break
return ORF_sequences
.
ATOzTOA の関数と私の関数の 2 つの関数を、欠陥を明らかにするfdnaシーケンスと比較しました。これは、私が説明したことを正当化します。
from find_ORF_sequences import find_ORF_seq
from ATOz_get_sequences import getSequences
fdna = 'atgggatggtagatggatgggATGGGGTGA'
print 'fdna == %s' % fdna
print 'find_ORF_seq(fdna)\n',find_ORF_seq(fdna)
print 'getSequences(fdna)\n',getSequences(fdna)
結果
fdna == atgggatggtagatggatgggATGGGGTGA
find_ORF_seq(fdna)
['ATGGGATGGTAG', 'ATGGTAG', 'ATGGATGGGATGGGGTGA', 'ATGGGATGGGGTGA']
getSequences(fdna)
['ATGGGATGGTAG', 'ATGGATGGGATGGGGTGA']
.
しかし、結局のところ、おそらく、私は.... :の最後の
ように、別のマッチングの内部部分である一致が必要ですか?'ATGGGATGGGGTGA'
'ATGGATGGGATGGGGTGA'
そうでない場合は、ATOzTOA の回答も一致します。