Praca na modułach - pomoc

0

Witam, mam problem z napisaniem programu dla tego zadania:
"Napisz program, który pobiera od użytkownika maksymalna długość DNA, lecz nie mniejszą niż 9, program pyta do skutku aż poda min.9. Następnie generuje losową sekwencje DNA o losowej długości, niezerowej i nieprzekraczającej maksymalnej liczy oraz podzielnej przez 3. Dodaje kodon start( ATG). Następnie dzieli sekwencje na kodony i wprowadza losowe pojedyncze mutacje w 3 innych, losowych kodonach. Jeśli ocalał kodon start wyświetla końcową sekwencje. Jeśli mutacje naruszyły kodon start, należy napisać, że nie udało się stworzyć genu. Mutacje można wprowadzić małymi literami."

Starałam się sama napisać, aczkolwiek na tym poziomie kończą się moje umiejętności z pisania programu:

from random import choice
from random import randint
import random

dlug=int(raw_input("Podaj maksymalna dlugosc sekwencji, minimum 9: "))
while dlug < 9:
    dlug=int(raw_input("Podaj dlugosc sekwencji MINIMUM 9: "))

losseq_mut=""

nuk = ["A","C","T","G"]
mutacja = ["a","c","t","g"]
losseq_mut=""
y=1
while y%3!=0:
    y=random.randint(1,dlug)
losseq=""
for k in range(y):
    losseq+=choice(nuk)
dna="ATG"+losseq
for j in range(0,len(dna),3):
    print dna[j:j+3]

u=int(y)+3
print "Dlugosc wylosowanej sekwencji z kodonem start wynosi %i" %(u)

t=random.randint(0,u)        
r=random.randint(0,u)
e=random.randint(0,u)
while r==t:
    r=random.randint(0,u)

while e==t or e==r:
    e=random.randint(0,u)
                
for s in range(len(dna)):
            
    if s == t or s == e or s == r:
        losseq_mut+=choice(mutacja)
    else:
        losseq_mut+=dna[s]
                
if losseq_mut.startswith("ATG"):
    print losseq_mut
else:
    print "nie udalo sie"

Jedynie czego nie wiem jak zrobić to to, aby nie było więcej niż 1 mutacja w kodonie. Będę wdzięczna za pomoc!!`

0

To co zrobiłaś do tej pory ma sens ale zaproponuję parę poprawek.

losseq_mut=""
 
nuk = ["A","C","T","G"]
mutacja = ["a","c","t","g"]
losseq_mut=""

Wielokrotnie definiujesz losseq_mut. nuk można przechowac jako string (string w Pythonie możemy iterować jak listę). mutacja to po prostu nuk.lower() - na razie to ominę (później wskażę dlaczego):

nuk = 'ACTG'

y=1
while y%3!=0:
    y=random.randint(1,dlug)

Działa ale da się sprytniej. Jeżeli chcemy tylko losowe podzielne przez 3 liczby mniejsze od dlug - to zgodnie z matematyką będą to tylko wielokrotności 3 mieszczące się w dlug. Wystarczy więc podzielić dlug i zaokrąglić w dół aby uzyskać liczbę 3. Wylosować liczbę od 1 do tej liczby i pomnożyć przez 3. Przykład:

y = random.randint(1, dlug//3) * 3
losseq=""
for k in range(y):
    losseq+=choice(nuk)

Stringi w Pythonie sa immutable - oznacza to, że nie możemy ich zmieniać. Zapis += nie dodaje do istniejącego stringa a po prostu tworzy nowy string ze starego i nowego. Dlatego wydajniej jest napisać:

losseq = ''.join(choice(nuk) for k in range(y))

Co do samego problemu "Jedynie czego nie wiem jak zrobić to to, aby nie było więcej niż 1 mutacja w kodonie" - wystarczy traktować sekwencję jako listę kodonów i wybrać losowo 3 kodony i dokonać jednej zmiany. Podział w zasadzie już masz:

dna="ATG"+losseq
for j in range(0,len(dna),3):
    print dna[j:j+3]

Zamień to na listę kodonow:

dna = ['ATG']
for j in range(0,len(losseq),3):
   dna.append(losseq[j:j+3])
print(dna)
print "Dlugosc wylosowanej sekwencji z kodonem start wynosi %i" %(len(dna)*3)
t=random.randint(0,u)        
r=random.randint(0,u)
e=random.randint(0,u)
while r==t:
    r=random.randint(0,u)
 
while e==t or e==r:
    e=random.randint(0,u)

Żeby wybrać 3 losowe liczby, które są od siebie różne można zastosować poniższy sposób. Wybiera 3 próbki z podanej listy/generatora - tutaj range z len(dna):

t,r,e = random.sample(range(len(dna)), 3)

Teraz możemy po prostu odnieść się do 3 wybranych indeksów. Uzyłem zapisu z kodon[:i] + ran.. ponieważ jak wspomniałem nie możemy modyfikowac stringow a jedynie tworzyc nowe na podstawie obecnych :

def mutate(kodon, mutations):
   i = random.randint(0, 3)
   return kodon[:i] + random.choice(mutations) + kodon[i+1:]

dna[t] = mutate(dna[t], nuk.lower())
dna[r] = mutate(dna[r], nuk.lower())
dna[e] = mutate(dna[e], nuk.lower())

I potem wystarczy sprawdzic czy dna[0]=='ATG'.

1

Ostatecznie:

import random

def mutate(kodon, mutations):
   i = random.randint(0, 3)
   return kodon[:i] + random.choice(mutations) + kodon[i+1:]
 
dlug=int(raw_input("Podaj maksymalna dlugosc sekwencji, minimum 9: "))
while dlug < 9:
    dlug=int(raw_input("Podaj dlugosc sekwencji MINIMUM 9: "))
 
 
nuk = 'ACTG'
y = random.randint(1, dlug//3) * 3

losseq = ''.join(random.choice(nuk) for k in range(y))

dna = ['ATG']
for j in range(0,len(losseq),3):
   dna.append(losseq[j:j+3])
print(dna)
print "Dlugosc wylosowanej sekwencji z kodonem start wynosi %i" %(len(dna)*3)
 
random_indexes = random.sample(range(len(dna)), 3)
for index in random_indexes:
  dna[index] = mutate(dna[index], nuk.lower())
 
if dna[0]=="ATG":
    print (dna)
else:
    print ("nie udalo sie")

Literówki i drobne błędy jak najbardziej możliwe - sprawdź.

1 użytkowników online, w tym zalogowanych: 0, gości: 1