Преждевременная остановка цикла Python

#python #range #bioinformatics

#python #диапазон #биоинформатика

Вопрос:

Я пытаюсь преобразовать последовательность ДНК в аминокислотную последовательность. У меня есть словарь кодонов:

 codon_mapping = {'AAA': 'K','AAC': 'N','AAG': 'K','AAT': 'N','ACA': 'T','ACC': 'T','ACG': 'T','ACT': 'T','AGA': 'R','AGC': 'S','AGG': 'R','AGT': 'S','ATA': 'I','ATC': 'I','ATG': 'M','ATT': 'I','CAA': 'Q','CAC': 'H','CAG': 'Q','CAT': 'H','CCA': 'P','CCC': 'P','CCG': 'P','CCT': 'P','CGA': 'R','CGC': 'R','CGG': 'R','CGT': 'R','CTA': 'L','CTC': 'L','CTG': 'L','CTT': 'L','GAA': 'E','GAC': 'D','GAG': 'E','GAT': 'D','GCA': 'A','GCC': 'A','GCG': 'A','GCT': 'A','GGA': 'G','GGC': 'G','GGG': 'G','GGT': 'G','GTA': 'V','GTC': 'V','GTG': 'V','GTT': 'V','TAA': '*','TAC': 'Y','TAG': '*','TAT': 'Y','TCA': 'S','TCC': 'S','TCG': 'S','TCT': 'S','TGA': '*','TGC': 'C','TGG': 'W','TGT': 'C','TTA': 'L','TTC': 'F','TTG': 'L','TTT': 'F'}
  

И последовательность ввода:

 seq = 'ATGTATGGCTAGCTTACTACTGCGCACTGATGTGGCTATCGATCGCTGGTCGTTGCTGACCGAGCTAAA'
  

В настоящее время у меня есть этот код:

 #import re
import re

#find the start codons in the sequence
starts=[m.start() for m in re.finditer('ATG', seq)]

#establish new dictionary
seqDictionary={}
#translate sequences
for i in starts:
    mySeq=seq[i:]
    translated=''
    for n in range(0, len(mySeq), 3):
        print(mySeq[n:n 3])
        if codon_mapping[mySeq[n:n 3]] != '*':
            translated  = codon_mapping[mySeq[n:n 3]]
        if codon_mapping[seq[n:n 3]] == '*':
            break 
    print("translated: "   translated)
    seqDictionary[i]=(translated)
print(seqDictionary)
            
AA_frame1 = seqDictionary[0] 
AA_frame2 = seqDictionary[4] 
AA_frame3 = seqDictionary[29]
AA_longest = None 
  

проблема в том, что для второй и третьей последовательностей (с позиций 4 и 29 соответственно) цикл for завершается после четвертой аминокислоты, даже если это не стоп-кодоны.

Вывод приведенного выше кода:

 ATG
TAT
GGC
TAG
translated: MYG
ATG
GCT
AGC
TTA
translated: MASL
ATG
TGG
CTA
TCG
translated: MWLS
{0: 'MYG', 4: 'MASL', 29: 'MWLS'}
  

Я не получаю никаких сообщений об ошибках, и я не могу понять, почему цикл завершается. Я знаю, что правильными решениями для переведенных последовательностей являются:

 MYG
MASLLLRTDVAIDRWSLLTEL
MWLSIAGRC
  

Редактировать, этот окончательный код сработал:

 #import re
import re

#find the start codons in the sequence
starts=[m.start() for m in re.finditer('ATG', seq)]

#establish new dictionary
seqDictionary={}
#translate sequences
for i in starts:
    mySeq=seq[i:]
    translated=''
    for n in range(0, len(mySeq), 3):
        if len(mySeq[n:n 3]) < 3:
            break
        if codon_mapping[mySeq[n:n 3]] == '*':
            break
        else:
            translated  = codon_mapping[mySeq[n:n 3]]
    seqDictionary[i]=(translated)
print(seqDictionary)
  

Вывод:

 {0: 'MYG', 4: 'MASLLLRTDVAIDRWSLLTEL', 29: 'MWLSIAGRC'}
  

Комментарии:

1. это из-за опечатки? if codon_mapping[seq[n:n 3]] == '*': , должно seq быть mySeq ?

2. Я также подозреваю некоторые недоразумения, связанные с seq и mySeq . Почему бы и нет if codon_mapping[mySeq[n:n 3]] != '*': #...; else: break ?

Ответ №1:

 if codon_mapping[mySeq[n:n 3]] != '*':
    translated  = codon_mapping[mySeq[n:n 3]]
if codon_mapping[seq[n:n 3]] == '*':
    break 
  

здесь вы не проверяете одно и то же. Первый if проверяет mySeq , второй if проверяет seq .

это лучше записать как if else, чем два ifs

 if codon_mapping[mySeq[n:n 3]] == '*':
    break
else:
    translated  = codon_mapping[mySeq[n:n 3]]
  

Комментарии:

1. если вы делаете перерыв, if почему у else:

2. это один оператор if для достижения обоих результатов, у вас есть два оператора if, которые эффективно проверяют одно и то же. этот способ более аккуратный. И если бы вы сделали это таким образом, у вас не было бы возможности совершить ошибку, которую вы совершили, потому что вы не дублируете код.

3. @rioV8 извините, вы не OP, я неправильно прочитал ваш вопрос! Вы правы, else не требуется. Но для примера здесь это помогает подчеркнуть, как if / else заменяет два if . В коде OP есть много вещей, которые я бы улучшил, если бы оптимизировал.

Ответ №2:

Вы должны проверить, есть ли триплет в словаре

 for i in starts:
    mySeq=seq[i:]
    translated=''
    for n in range(0, len(mySeq), 3):
        subSeq = mySeq[n:n 3]
        print(subSeq)
        aAcid = codon_mapping.get(subSeq)
        if (not aAcid) or aAcid == '*': break
        translated  = aAcid
    print("translated: "   translated)
    seqDictionary[i]=(translated)
  

С itertools переводом может быть записан в одну строку

 import itertools
#establish new dictionary
seqDictionary={}
#translate sequences
for m in re.finditer('ATG', seq):
    start = m.start()
    translated =''.join(itertools.takewhile(lambda aa: aa and aa != '*', (codon_mapping.get(seq[n:n 3]) for n in range(start, len(seq), 3)) ))
    print("translated: "   translated)
    seqDictionary[start] = translated
print(seqDictionary)