Ćwiczenie 3: Analiza sekwencji nukleotydowych. Tworzenie

advertisement
Ćwiczenie 3: Analiza sekwencji nukleotydowych. Tworzenie programów do
analizy sekwencji DNA
1 Cel
Zapoznanie się z podstawowymi funkcjami pakietu Biopython, parsowanie sekwencji z plików w
formacie fasta i GenBank, tworzenie prostych programów do analizy danych biologicznych.
2 Wprowadzenie
Można przyjąć, że głównym obiektem zainteresowania w bioinformatyce jest sekwencja. W
związku z tym od niej rozpoczniemy przegląd możliwości jakie daje nam Biopython. Spróbujmy
przypisać zmiennej moja_sek następującą sekwencję: „AGTACACTGGT”. Najpierw importujemy
z modułu Bio.Seq obiekt Seq:
>>> from Bio.Seq import Seq
Następnie przypisujemy wyżej wspomnianą sekwencję korzystając z obiektu Seq:
>>>moja_sek = Seq("AGTACACTGGT")
Teraz możemy ją wywołać:
>>>moja_sek
Seq(’AGTACACTGGT’, Alphabet())
>>> print moja_sek
AGTACACTGGT
>>> moja_sek.alphabet
Alphabet()
Moja_sek jest obiektem o nieustalonym alfabecie, gdyż nie podaliśmy, czy ma to być DNA czy
białko. Poza tym, że Seq posiada alfabet, różni się on od zwykłego ciągu znaków w Pythonie. Dla
ciągu znaków nie byłoby możliwości uzyskania zasad komplementarnych:
>>> moja_sek.complement()
Seq(’TCATGTGACCA’, Alphabet())
czy też zasad komplementarnych w odwróconej sekwencji:
>>>moja_sek.reverse_complement()
Seq(’ACCAGTGTACT’, Alphabet())
Duża część zadań bioinformatycznych związana jest z obróbką rekordów sekwencji, które
zapisywane są w postaci wielu różnych formatów plików. Rekordy te zawierają cenne i
interesujące informacje biologiczne, ale zanim będą mogły być opracowywane za pomocą języka
programowania (takiego jak Python), konieczne jest poddanie ich tzw. parsingowi. Obecnie
zapoznamy się z modułem Bio.SeqIO. Dla przykładu wczytamy plik w formacie fasta o nazwie
termit (4 sekwencje będące wynikiem przeszukiwania bazy danych NCBI Nucleotide dla kwerendy
„Serritermitidae”). W tym celu wpisujemy następujący kod:
>>>from Bio import SeqIO
1
>>> for rekord_sek in SeqIO.parse("termit.fasta", "fasta"):
print rekord_sek.id
print repr(rekord_sek.seq)
print len(rekord_sek)
W rezultacie powinniśmy otrzymać następujący wynik:
gi|48476610|gb|AY553161.1|
Seq('CACCCAGAAGTATATATTTTGATTCTACCAGGATTTGGTATAATTTCTCACATC...ATC', SingleLetterAlphabet())
816
gi|8886830|gb|AF220598.1|
Seq('ATGGCAACATGAATAAACCTTAATCTCCAAGACGGAGCATCCCCAATCATAGAA...GAG', SingleLetterAlphabet())
667
gi|8886805|gb|AF220565.1|
Seq('AATGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTGGACAGTTACTTGGATA...AGG', SingleLetterAlphabet())
1718
gi|12965151|gb|AF262577.1|AF262577
Seq('TATTTCCCGATTTTGGAGGAGTTAACAATTGGTGTGTTGTTTATTGTTTTATAA...GAT', SingleLetterAlphabet())
818
Zauważmy, że format FASTA nie specyfikuje alfabetu, dlatego Bio.SeqIO wybrał domyślną opcję
SingleLetterAlphabet(), raczej niż specyficzny kod dla DNA.
Spróbujmy teraz wczytać ten sam plik w formacie GenBank. Jedyna różnica jaka pojawia się w tym
wypadku dotyczy rozszerzenia pliku (.gb) oraz formatu („genbank”, zamiast „fasta” ):
>>>for rekord_sek in SeqIO.parse("termit.gb", "genbank"):
print rekord_sek.id
print repr(rekord_sek.seq)
print len(rekord_sek)
Powinniśmy otrzymać następujący wynik:
AY553161.1
Seq('CACCCAGAAGTATATATTTTGATTCTACCAGGATTTGGTATAATTTCTCACATC...ATC', IUPACAmbiguousDNA())
816
AF220598.1
Seq('ATGGCAACATGAATAAACCTTAATCTCCAAGACGGAGCATCCCCAATCATAGAA...GAG',
IUPACAmbiguousDNA())
667
AF220565.1
Seq('AATGGCTCATTAAATCAGTTATGGTTCCTTAGATGGTGGACAGTTACTTGGATA...AGG', IUPACAmbiguousDNA())
1718
AF262577.1
Seq('TATTTCCCGATTTTGGAGGAGTTAACAATTGGTGTGTTGTTTATTGTTTTATAA...GAT', IUPACAmbiguousDNA())
818
Zauważmy, że tym razem
(IUPACAmbiguousDNA()) .
Bio.SeqIO
był
w
stanie
wybrać
sensowny
alfabet
3.1 Sekwencje i alfabety
Obiekt alfabet jest w zasadzie głównym elementem obiektu Seq, który odróżnia go od zwykłego
ciągu znaków (string). Obecnie dostępne alfabety w Biopythonie są zawarte w module
Bio.Alphabet. Przy analizie sekwencji DNA, RNA i białek, będziemy korzystać z alfabetów IUPAC
(Międzynarodowa Unia Chemii Czystej i Stosowanej). Bio.Alphabet.IUPAC dostarcza podstawowe
typy alfabetów dla białek, DNA i RNA, ale dodatkowo umożliwia też ich modyfikację i
2
dostosowywanie do własnych potrzeb. Np. dla białek istnieje podstawowa klasa IUPACProtein, ale
jest też specjalna klasa ExtendedIUPACProtein obejmująca elementy „U” (lub „Sec” dla
selenocysteiny) i „O” (lub „Pyr” dla pirolizyny), a także niejednoznaczne symbole „B” (lub „Asx”
dla asparaginy lub kwasu asparaginowego), „Z” (lub „Glx” dla glutaminy lub kwasu
glutaminowego”), „J” (lub „Xle” dla leucyny lub izoleucyny) oraz „X” (lub „Xxx” dla nieznanego
aminokwasu). Dla DNA można wybrać alfabet IUPACUnabiguousDNA, który uwzględnia tylko
podstawowe zasady, IUPACAmbiguousDNA (który uwzględnia wszystkie zasady niejednoznaczne)
oraz ExtendedIUPACDNA, który zezwala na stosowanie liter dla zmodyfikowanych zasad.
Podobnie dla RNA mamy alfabety IUPACAmbiguousRNA i IUPACUnambiguousRNA. Korzyści
płynące z obecności klasy typu alfabet są dwojakiego rodzaju. Po pierwsze pozwala to na
uwzględnienie rodzaju informacji (sekwencji) zawartej w postaci obiektu Seq. Po drugie,
umożliwia ograniczenie typu informacji i służyć może jako narzędzie sprawdzające typ sekwencji.
Sekwencję niejednoznaczną z domyślnym ogólnym alfabetem tworzymy w następujący sposób:
>>> from Bio.Seq import Seq
>>> moja_sek = Seq("AGTACACTGGT")
>>> moja_sek
Seq('AGTACACTGGT', Alphabet())
>>> moja_sek.alphabet
Alphabet()
Zawsze powinniśmy podać rodzaj stosowanego alfabetu tam, gdzie to możliwe:
>>> from Bio.Alphabet import IUPAC
>>> moja_sek = Seq("AGTACACTGGT", IUPAC.unambiguous_dna)
>>> moja_sek
Seq('AGTACACTGGT', IUPACUnambiguousDNA())
>>> moja_sek.alphabet
IUPACUnambiguousDNA()
Jeżeli byłby to łańcuch aminokwasowy, mielibyśmy:
>>> from Bio.Alphabet import IUPAC
>>> moje_bialko = Seq("AGTACACTGGT", IUPAC.protein)
>>> moje_bialko
Seq('AGTACACTGGT', IUPACProtein())
>>> moje_bialko.alphabet
IUPACProtein()
W wielu przypadkach możemy postępować z obiektem Seq, tak jak byłby to zwykły ciąg znaków.
Możemy np. określić jego długość itp.:
>>>from Bio.Seq import Seq
>>>from Bio.Alphabet import IUPAC
>>>moja_sek = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC", IUPAC.unambiguous_dna)
>>>for indeks, litera in enumerate(moja_sek):
print indeks, litera
print len(litera)
Otrzymamy wówczas zestawienie wszystkich indeksów, zasad oraz długości ciągów zasad. Można
też odwoływać, się do poszczególnych elementów sekwencji poprzez ich indeksy:
>>> print moja_sek[0]
G
>>> print moja_sek[2]
T
3
>>> print moja_sek[-1]
C
Ostatnia komenda przywołuje ostatnią zasadę. Podobnie jak w przypadku ciągu znaków w
Pythonie, można zliczać ile razy występuje dany element:
>>> "AAAA".count("AA")
2
>>> Seq("AAAA").count("AA")
2
Jednak w niektórych przypadkach potrzebne może nam być określenie liczby zachodzących na
siebie elementów. Przy pojedynczym znaku nie ma to znaczenia:
>>> len(moja_sek)
32
>>> moja_sek.count("G")
9
>>> 100 * float(moja_sek.count("G") + moja_sek.count("C")) / len(moja_sek)
46.875
Ostatnia komenda w powyższym kodzie wylicza procent zasad G i C w sekwencji. Zamiast tego,
można wykorzystać wbudowaną funkcję zliczającą procent zasad G i C:
>>> from Bio.SeqUtils import GC
>>> moja_sek = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC", IUPAC.unambiguous_dna)
>>> GC(moja_sek)
46.875
Zauważmy, że funkcja Bio.SeqUtils.GC() obsługuje także sekwencje pisane raz małymi, raz
dużymi literami oraz zawierające symbol S, dla oznaczenia G lub C.
3.2 Zadania
1. Napisz skrypt o nazwie pobieranie.py, który będzie parsował sekwencję o ścieżce dostępu (np.
C:\Users\Public\....) i formacie (fasta, genbank) podanym przez użytkownika. Przykładowy efekt
działania skryptu powinien być następujący:
Podaj nazwe pliku lub sciezke:C:\Users\daniel\Desktop\sekwencja.fasta
Podaj format pliku:fasta
gi|2765658|emb|Z78533.1|CIZ78533
Seq('CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGATGAGACCGTGG...CGC',
SingleLetterAlphabet())
740
gi|2765657|emb|Z78532.1|CCZ78532
Seq('CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGTTGAGACAACAG...GGC',
SingleLetterAlphabet())
753
gi|2765656|emb|Z78531.1|CFZ78531
Seq('CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGTTGAGACAGCAG...TAA',
SingleLetterAlphabet())
….
2. Napisz skrypt o nazwie odwrocona.py, który będzie podawał sekwencję komplementarną i
odwróconą sekwencję komplementarną do sekwencji zadanej przez użytkownika. Przykładowy
efekt działania skryptu powinien być następujący:
4
Podaj sekwencje DNA: TTTTTGGGGCAAATGCAAATGTCAA
Sewencja komplementarna to: AAAAACCCCGTTTACGTTTACAGTT
Sekwencja komplementarna odwrocona to: TTGACATTTGCATTTGCCCCAAAAA
3. Rozszerz powyższy skrypt o następujące elementy: zadeklarowanie przez użytkownika rodzaju
alfabetu, podanie przez skrypt nazwy wybranego alfabetu, długości sekwencji, pierwszej i ostatniej
litery tej sekwencji, a także wyliczenie procentu zasad AT (zakładamy, że mamy do czynienia z
sekwencją nukleotydową). Przykładowy efekt powinien być następujący:
Podaj sekwencje DNA: GGGTACAGTTCAAGTGTAACA
Podaj rodzaj alfabetu: IUPAC.unambiguous_dna
Sekwencja komplementarna to: CCCATGTCAAGTTCACATTGT
Sekwencja komplementarna odwrocona to: TGTTACACTTGAACTGTACCC
Rodzaj wybranego alfabetu to: IUPACUnambiguousDNA()
Dlugosc sekwencji: 21 , Pierwsza litera to: G
Ostatnia litera to: A , Procent zasad AT: 57.1428571429
4.1 Wycinanie fragmentów sekwencji
Spróbujemy teraz wyciąć fragment sekwencji:
>>>from Bio.Seq import Seq
>>>moja_sek = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC", IUPAC.unambiguous_dna)
>>> moja_sek[4:12]
Seq(’GATGGGCC’, IUPACUnambiguousDNA())
Pierwszym elementem powyższej sekwencji jest 0. Przy wycinaniu pierwszy element jest włączany
do nowej sekwencji, a ostatni pomijany. Np. w powyższym przykładzie 4. element zostaje, a 12 jest
pomijany. Ponadto, nowo utworzona sekwencja jest znowu obiektem Seq zachowującym alfabet
pierwotnej sekwencji.
Podobnie jak w Pythonie, można użyć do wycinania sekwencji opcje start, stop i stride (wielkość
kroku wybrana domyślnie jako 1). Możemy np. uzyskać pozycje 1., 2. i 3. kodonu sekwencji:
>>> moja_sek[0::3]
Seq(’GCTGTAGTAAG’, IUPACUnambiguousDNA())
>>> moja_sek[1::3]
Seq(’AGGCATGCATC’, IUPACUnambiguousDNA())
>>> moja_sek[2::3]
Seq(’TAGCTAAGAC’, IUPACUnambiguousDNA())
Poza tym można odwrócić sekwencję stosując ujemny krok (stride=-1):
>>> moja_sek[::-1]
Seq(’CGCTAAAAGCTAGGATATATCCGGGTAGCTAG’, IUPACUnambiguousDNA())
4.2 Zamiana obiektów Seq na ciągi znaków
Jeżeli chcemy zamienić obiekt Seq na zwykły ciąg znaków (string) stosujemy funkcję str:
>>> str(moja_sek)
’GATCGATGGGCCTATATAGGATCGAAAATCGC’
Można w tym celu wykorzystać także funkcję print:
>>> print moja_sek
GATCGATGGGCCTATATAGGATCGAAAATCGC
5
Obiekt Seq można także stosować bezpośrednio ze znakiem %s przy formatowaniu ciągu znaków w
Pythonie lub z operatorem interpolacji %:
>>> fasta_format_string = ">Nazwa\n%s\n" % moja_sek
>>> print fasta_format_string
>Nazwa
GATCGATGGGCCTATATAGGATCGAAAATCGC
Powyższy kod generuje prosty rekord w formacie FASTA.
4.3 Zadania
1. Utwórz skrypt o nazwie wycinek.py, który będzie wycinał fragment o podanych przez
użytkownika współrzędnych (indeks początkowy i końcowy) z sekwencji także podanej przez
użytkownika. Zastosuj przy tym alfabet IUPAC.unambiguous_dna. Przykładowy efekt powinien
być następujący:
Podaj sekwencje DNA: CCAAATGTTACTTAGCT
Podaj indeks poczatkowy: 4
Podaj indeks koncowy: 12
Wyciety fragment to: ATGTTACT
2. Utwórz nowy skrypt krok.py, który dla zadanej przy użytkownika sekwencji będzie podwał co
trzecią zasadę począwszy od 1,2 i 3 litery sekwencji, a na końcu odwróci tą sekwencję. Skorzystaj
przy tym z alfabetu IUPAC.unambiguous_dna. Przykładowy rezultat powinien wyglądać
następująco:
Podaj sekwencje DNA: GGGTACGGTAAACGT
Kolejne zasady poczawszy od 0 przy kroku rownym 3: GTGAC
Kolejne zasady poczawszy od 1 przy kroku rownym 3: GAGAG
Kolejne zasady poczawszy od 2 przy kroku rownym 3: GCTAT
Sekwencja odwrocona: TGCAAATGGCATGGG
5.1 Łączenie i dodawanie sekwencji
Obiekty Seq mogą być ze sobą łączone tak, jak łączy się w Pythonie zwykłe ciągi znaków. Nie
można jednak łączyć ze sobą sekwencji o niekompatybilnych alfabetach (np. sekwencja białkowa i
nukleotydowa). Gdyby jednak bardzo nam na tym zależało, to najpierw należy przypisać obu
sekwencjom alfabet ogólny (generic alphabet). Poniższy przykład dotyczy dodania sekwencji DNA
z alfabetem ogólnym do sekwencji DNA z alfabetem jednoznacznym IUPAC, co daje w rezultacie
sekwencję z alfabetem niejednoznacznym:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import generic_nucleotide
>>> from Bio.Alphabet import IUPAC
>>> nuk_sek = Seq("GATCGATGC", generic_nucleotide)
>>> dna_sek = Seq("ACGT", IUPAC.unambiguous_dna)
>>> nuk_sek
Seq(’GATCGATGC’, NucleotideAlphabet())
>>> dna_sek
Seq(’ACGT’, IUPACUnambiguousDNA())
>>> nuk_sek + dna_sek
Seq(’GATCGATGCACGT’, NucleotideAlphabet())
6
5.2 Zmiana wielkości znaków
Python posiada bardzo użyteczną funkcję zmiany wielkości znaków w ciągu znaków. To samo
można wykonać w Biopythonie dla obiektu Seq, przy czym brany jest pod uwagę rodzaj alfabetu:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import generic_dna
>>> dna_sek = Seq("acgtACGT", generic_dna)
>>> dna_sek
Seq(’acgtACGT’, DNAAlphabet())
>>> dna_sek.upper()
Seq(’ACGTACGT’, DNAAlphabet())
>>> dna_sek.lower()
Seq(’acgtacgt’, DNAAlphabet())
Opcja ta jest użyteczna przy przeszukiwaniu sekwencji bez względu na wielkość znaków:
>>> "GTAC" in dna_sek
False
>>> "GTAC" in dna_sek.upper()
True
Należy zwrócić uwagę, że alfabety IUPAC funkcjonują tylko dla sekwencji pisanych dużymi
literami:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> dna_sek = Seq("ACGT", IUPAC.unambiguous_dna)
>>> dna_sek
Seq(’ACGT’, IUPACUnambiguousDNA())
>>> dna_sek.lower()
Seq(’acgt’, DNAAlphabet())
5.3 Uzyskiwanie sekwencji komplementarnych i komplementarnych odwróconych
Możliwe jest uzyskiwanie sekwencji komplementarnych lub komplementarnych odwróconych dla
obiektu Seq:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> moja_sek = Seq("GATCGATGGGCCTATATAGGATCGAAAATCGC", IUPAC.unambiguous_dna)
>>> moja_sek
Seq(’GATCGATGGGCCTATATAGGATCGAAAATCGC’, IUPACUnambiguousDNA())
>>> moja_sek.complement()
Seq(’CTAGCTACCCGGATATATCCTAGCTTTTAGCG’, IUPACUnambiguousDNA())
>>> moja_sek.reverse_complement()
Seq(’GCGATTTTCGATCCTATATAGGCCCATCGATC’, IUPACUnambiguousDNA())
Jak już wspomnieliśmy, najprostszą metodą odwrócenia sekwencji jest jej wycięcie przy kroku
równym -1:
>>> moja_sek[::-1]
Seq(’CGCTAAAAGCTAGGATATATCCGGGTAGCTAG’, IUPACUnambiguousDNA())
We wszystkich powyższych operacjach zachowywana jest informacja o alfabecie. Ma to
zastosowanie na wypadek, gdybyśmy np. niechcący spróbowali uzyskać sekwencję
komplementarną do aminokwasowej:
7
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> sek_bialkowa = Seq("EVRNAK", IUPAC.protein)
>>> sek_bialkowa.complement()
...
ValueError: Proteins do not have complements!
5.4 Zadania
1. Napisz skrypt (dowolna nazwa), który będzie łączył dwie sekwencje nukleotydowe podane przez
użytkownika skryptu (skorzystaj z alfabetu generic_nucleotide), poda połączoną sekwencję, zmieni
wielkość liter tej sekwencji na małe, pozwoli stwierdzić, czy w ramach tej sekwencji występuje
zadana przez użytkownika krótsza sekwencja, a na końcu poda sekwencję komplementarną i
komplementarną odwróconą. Przykładowy wynik działania takiego skryptu:
Podaj pierwsza sekwencje: gtttgattcgt
Podaj druga sekwencje: aaacccgtaagc
Sekwencja polaczona: gtttgattcgtaaacccgtaagc
Sekwencja pisana malymi literami: gtttgattcgtaaacccgtaagc
Podaj fragment do wyszukiwania (male litery): aaa
True
Sekwencja komplementarna: caaactaagcatttgggcattcg
i komplementarna odwrocona: gcttacgggtttacgaatcaaac
6.1 Transkrypcja
Przejdziemy teraz do transkrypcji. Na początku należy zauważyć, że w naturze transkrypcja
odbywa się w oparciu o nić komplementarną do kodującej, podczas gdy w bioinformatyce
pracujemy bezpośrednio na nici kodującej. Wynika to z faktu, że w ten sposób można łatwo
przepisać DNA na RNA zamieniając T na U.
Zanim dokonamy transkrypcji utwórzmy obiekty Seq dla nici kodującej i komplementarnej:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> kodujacy_dna = Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG",
IUPAC.unambiguous_dna)
>>> kodujacy_dna
Seq(’ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG’, IUPACUnambiguousDNA())
>>> matrycowy_dna = kodujacy_dna.reverse_complement()
>>> matrycowy_dna
Seq(’CTATCGGGCACCCTTTCAGCGGCCCATTACAATGGCCAT’, IUPACUnambiguousDNA())
Teraz przepiszemy nić kodującą DNA na mRNA korzystając z wbudowanej metody transcribe:
>>> kodujacy_dna
Seq(’ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG’, IUPACUnambiguousDNA())
>>> informacyjny_rna = kodujacy_dna.transcribe()
>>> informacyjny_rna
Seq(’AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG’, IUPACUnambiguousRNA())
Jak widać w powyższym przykładzie, wszystko co czyni metoda transcribe polega na zamianie T na
U i dostosowaniu alfabetu. Gdybyśmy jednak chcieli dokonać prawdziwej transkrypcji na nici
matrycowej, to można to wykonać w dwóch następujących etapach:
8
>>> matrycowy_dna.reverse_complement().transcribe()
Seq(’AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG’, IUPACUnambiguousRNA())
Obiekt Seq umożliwia także odwrotną transkrypcję z mRNA na kodującą nić DNA, co znowu
polega na zamianie U na T i dostosowaniu alfabetu:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> informacyjny_rna = Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG",
IUPAC.unambiguous_rna)
>>> informacyjny_rna
Seq(’AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG’, IUPACUnambiguousRNA())
>>> informacyjny_rna.back_transcribe()
Seq(’ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG’, IUPACUnambiguousDNA())
6.2 Translacja
Pozostając przy tym samym przykładzie, co przy transkrypcji spróbujemy teraz przepisać mRNA na
białko:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> informacyjny_rna = Seq("AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG",
IUPAC.unambiguous_rna)
>>> informacyjny_rna
Seq(’AUGGCCAUUGUAAUGGGCCGCUGAAAGGGUGCCCGAUAG’, IUPACUnambiguousRNA())
>>> informacyjny_rna.translate()
Seq(’MAIVMGR*KGAR*’, HasStopCodon(IUPACProtein(), ’*’))
Można także dokonać translacji bezpośrednio z kodującej nici DNA:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> kodujacy_dna = Seq("ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG",
IUPAC.unambiguous_dna)
>>> kodujacy_dna
Seq(’ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG’, IUPACUnambiguousDNA())
>>> kodujacy_dna.translate()
Seq(’MAIVMGR*KGAR*’, HasStopCodon(IUPACProtein(), ’*’))
Zauważmy, że w powyższej sekwencji oprócz końcowego kodonu stop, występuje kodon stop
wewnątrz sekwencji (oznaczony gwiazdką). Przykład ten ilustruje konsekwencje stosowania
różnych rodzajów kodu genetycznego przy tłumaczeniu sekwencji nukleotydowej na białko.
Rodzaje kodu genetycznego stosowane w Biopythonie są zgodne ze standardem NCBI. Załóżmy, że
mamy do czynienia z sekwencją mitochondrialną. Musimy wybrać odpowiedni kod genetyczny:
>>> kodujacy_dna.translate(table="Vertebrate Mitochondrial")
Seq(’MAIVMGRWKGAR*’, HasStopCodon(IUPACProtein(), ’*’))
Rodzaj kodu genetycznego można podać też stosując jego numer wg NCBI. Poza tym, numer ten
podawany jest często w plikach sekwencji GenBank:
>>> kodujacy_dna.translate(table=2)
Seq(’MAIVMGRWKGAR*’, HasStopCodon(IUPACProtein(), ’*’))
Teraz możemy dokonać translacji do momentu wystąpienia pierwszego kodonu stop, czyli tak jak
9
dzieje się to w naturze:
>>> kodujacy_dna.translate()
Seq(’MAIVMGR*KGAR*’, HasStopCodon(IUPACProtein(), ’*’))
>>> kodujacy_dna.translate(to_stop=True)
Seq(’MAIVMGR’, IUPACProtein())
>>> kodujacy_dna.translate(table=2)
Seq(’MAIVMGRWKGAR*’, HasStopCodon(IUPACProtein(), ’*’))
>>> kodujacy_dna.translate(table=2, to_stop=True)
Seq(’MAIVMGRWKGAR’, IUPACProtein())
Zauważmy, że przy korzystaniu z argumentu to_stop kodon stop nie ulega translacji i znak kodonu
stop nie pojawia się w sekwencji. Można także samemu określić symbol kodonu stop, jeśli nie
podoba nam się domyślna gwiazdka:
>>> kodujacy_dna.translate(table=2, stop_symbol="@")
Seq(’MAIVMGRWKGAR@’, HasStopCodon(IUPACProtein(), ’@’))
Załóżmy teraz, że mamy do czynienia z regionem kodującym CDS (mRNA po splicingu),
składającym się z samych kodonów, zaczynającym się od kodonu start i kończącym się kodonem
stop, bez wewnętrznych kodonów stop. Zazwyczaj domyślna opcja translacji z zastosowanym
argumentem to_stop da oczekiwany wynik, ale w niektórych przypadkach mamy do czynienia z
niestandardowym kodem genetycznym, jak w przypadku bakterii.
>>>from Bio.Alphabet import generic_dna
>>>gen=Seq("GTGAAAAAGATGCAATCTATCGTACTCGCACTTTCCCTGGTTCTGGTCGCTCCCATGGCA
GCACAGGCTGCGGAAATTACGTTAGTCCCGTCAGTAAAATTACAGATAGGCGATCGTGATAATCGTGGCT
ATTACTGGGATGGAGGTCACTGGCGCGACCACGGCTGGTGGAAACAACATTATGAATGGCGAGGCAATC
GCTGGCACCTACACGGACCGCCGCCACCGCCGCGCCACCATAAGAAAGCTCCTCATGATCATCACGGC
GGTCATGGTCCAGGCAAACATCACCGCTAA", generic_dna)
>>> gen.translate(table="Bacterial")
Seq(’VKKMQSIVLALSLVLVAPMAAQAAEITLVPSVKLQIGDRDNRGYYWDGGHWRDH...HR*’,
HasStopCodon(ExtendedIUPACProtein(), ’*’)
>>> gen.translate(table="Bacterial", to_stop=True)
Seq(’VKKMQSIVLALSLVLVAPMAAQAAEITLVPSVKLQIGDRDNRGYYWDGGHWRDH...HHR’,
ExtendedIUPACProtein())
W kodzie genetycznym bakterii GTG jest kodonem startowym i podczas, gdy normalnie koduje
walinę, w tym wypadku koduje metioninę. Efekt taki uzyskamy, jeśli zaznaczymy, że mamy do
czynienia z kompletnym CDS:
>>> gen.translate(table="Bacterial", cds=True)
Seq(’MKKMQSIVLALSLVLVAPMAAQAAEITLVPSVKLQIGDRDNRGYYWDGGHWRDH...HHR’,
ExtendedIUPACProtein())
Oprócz tego, że poprawnie została dokonana translacja, stosując argument cds=True, mamy
pewność, że podany fragment sekwencji jest rzeczywiście regionem kodującym. Jeśli tak nie jest,
zostaniemy o tym powiadomieni.
6.3 Tabele translacji
Przy translacji sekwencji nukleotydowych wykorzystywane są tabele translacji zgodne ze
standardem NCBI. Obecnie skupimy się na dwóch rodzajach kodu genetycznego: standardowym i
mitochondrialnym kręgowców:
10
>>> from Bio.Data import CodonTable
>>> standard_table = CodonTable.unambiguous_dna_by_name["Standard"]
>>> mito_table = CodonTable.unambiguous_dna_by_name["Vertebrate Mitochondrial"]
Zamiast podawać pełne nazwy, można podać numery typów kodu genetycznego:
>>> from Bio.Data import CodonTable
>>> standard_table = CodonTable.unambiguous_dna_by_id[1]
>>> mito_table = CodonTable.unambiguous_dna_by_id[2]
Można porównać tabele kodu genetycznego drukując je:
>>>print standard_table
Table 1 Standard, SGC0
…....
>>> print mito_table
Table 2 Vertebrate Mitochondrial, SGC1
…..
Powyższe zestawienia są użyteczne, np. jeśli sami chcemy analizować sekwencje pod kątem
występowania genów:
>>> mito_table.stop_codons
[’TAA’, ’TAG’, ’AGA’, ’AGG’]
>>> mito_table.start_codons
[’ATT’, ’ATC’, ’ATA’, ’ATG’, ’GTG’]
>>> mito_table.forward_table["ACG"]
’T’
6.4 Zadania
1. Napisz skrypt translacja.py, dokonujący transkrypcji, a następnie translacji sekwencji pierwszego
rekordu w pliku sekwencja.fasta, tak, aby użytkownik mógł wybrać rodzaj tabeli translacji.
Translacja ma przebiegać do momentu wystąpienia pierwszego kodonu stop. Skrypt ma podawać
długość sekwencji mRNA oraz białka. Wykorzystaj następujący fragment kodu w celu przypisania
zmiennej dna sekwencji z pierwszego rekordu ww. pliku, wstawiając za „ścieżka dostępu” właściwą
ścieżkę:
>>>from Bio import SeqIO
>>>rekord_iterator = SeqIO.parse("ścieżka dostępu", "fasta")
>>>pierwszy_rekord = rekord_iterator.next()
>>>dna=pierwszy_rekord.seq
Efekt działania skryptu powinien być następujący:
mRNA:
CACCCAGAAGUAUAUAUUUUGAUUCUACCAGGAUUUGGUAUAAUUUCUCACAUCAUCUGCCACGAGA
GAGGUAAAAAGGAAGCCUUCGGAAACUUAGGAAUAAUUUUCGCCAUACUAGCAAUUGGCCUACUAGG
…......
11
Dlugosc mRNA: 816 zasad
Podaj numer tabeli translacji: 1
bialko:
HPEVYILILPGFGIISHIICHERGKKEAFGNLGIIFAILAIGLLGFVV
Dlugosc bialka: 48 aminokwasow
Porównaj wynik działania skryptu dla tabeli translacji =1 i 2. Czy rezultat jest taki sam?
2. Napisz podobny skrypt o nazwie odwrotna_transkrypcja.py, który będzie dokonywał transkrypcji
sekwencji DNA wczytanej z pliku sekwencja.fasta, a następnie dokonywał odwrotnej transkrypcji
powstałego mRNA. Przykładowy efekt działania skryptu:
mRNA:
CACCCAGAAGUAUAUAUUUUGAUUCUACCAGGAUUUGGUAUAAUUUCUCACAUCAUCUGCCACGAGA
GAGGUAAAAAGGAAGCCUUCGGAAACUUAGGAAUAAUUUUCGCCAUACUAGCAAUUGGCCUACUAGG
.......
Dlugosc mRNA: 816 zasad
Wynik odrotnej transkrypcji:
CACCCAGAAGTATATATTTTGATTCTACCAGGATTTGGTATAATTTCTCACATCATCTGCCACGAGAGAGGT
AAAAAGGAAGCCTTCGGAAACTTAGGAATAATTTTCGCCATACTAGCAATTGGCCTACTAGGATTTGTGGT.
......
Dlugosc DNA: 816 zasad
7.1 Porównywanie obiektów Seq
Ogólnie rzecz biorąc, porównywanie sekwencji jest bardzo złożonym problemem i nie ma łatwego
sposobu stwierdzenia, czy dwie sekwencje są jednakowe. Podstawowym problemem jest to, że
znaczenie litery w sekwencji zależy od jej rodzaju – czy jest to DNA, RNA czy białko. Biopython
wykorzystuje obiekty alfabetu jako część każdego obiektu Seq, w celu próby uchwycenia tej
informacji. Tak więc porównywanie dwóch obiektów Seq oznacza porównanie ich sekwencji jak i
alfabetów. Np. można sądzić, że dwie sekwencje DNA (obiekty Seq): Seq("ACGT",
IUPAC.unambiguous dna) i Seq("ACGT", IUPAC.ambiguous dna) są jednakowe, chociaż posiadają
różne alfabety. W zależności od rodzaju sekwencji może to być ważna informacja.
Problem może się jeszcze bardziej skomplikować. Załóżmy, że dwa obiekty Seq: Seq("ACGT",
IUPAC.unambiguous dna) i Seq("ACGT") (tj. domyślny alfabet ogólny) powinny być jednakowe.
Wtedy, logicznie rzecz biorąc obiekty Seq("ACGT", IUPAC.protein) and Seq("ACGT") też
powinny być jednakowe. W logice jeśli A=B i B=C, to A=C. Tak więc idąc tym tropem powinniśmy
uznać, że Seq("ACGT", IUPAC.unambiguous dna) i Seq("ACGT", IUPAC.protein) są jednakowe,
co większość ludzi uzna za błąd. Ten problem ma również swoje implikacje przy stosowaniu
obiektów Seq jako kluczy słowników Pythona.
Więc co robi Biopython? Test równości jest opcją domyślną obiektów Pythona – sprawdza on w
pamięci czy ma do czynienia z tymi samymi obiektami. Jest to bardzo restrykcyjny test:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> sek1 = Seq("ACGT", IUPAC.unambiguous_dna)
>>> sek2 = Seq("ACGT", IUPAC.unambiguous_dna)
>>> sek1 == sek2
False
>>> sek1 == sek1
True
W tym samym celu można wykorzystać funkcję id Pythona:
12
>>> id(sek1) == id(sek2)
False
>>> id(sek1) == id(sek1)
True
W codziennym użytkowaniu najczęściej mamy do czynienia z tym samym alfabetem, lub co
najmniej z tym samym typem sekwencji (DNA, RNA lub białko). W związku z tym, w celu
sprawdzenia, czy sekwencje są jednakowe, porównujemy je jako ciągi znaków (strings):
>>> str(sek1) == str(sek2)
True
>>> str(sek1) == str(sek1)
True
7.2 Obiekty MutableSeq
Tak jak w przypadku zwykłego ciągu znaków w Pythonie, obiekt Seq może być tylko odczytywany,
czyli w terminologii Pythona jest nieodmienny. Oprócz tego, że chcemy, aby obiekt Seq
funkcjonował jako ciąg znaków, ta funkcja domyślna jest także pożyteczna z innego powodu – w
wielu zastosowaniach biologicznych zależy nam na tym, aby analizowana sekwencja nie uległa
modyfikacji:
>>> from Bio.Seq import Seq
>>> from Bio.Alphabet import IUPAC
>>> moja_sek = Seq("GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA", IUPAC.unambiguous_dna)
>>> moja_sek[5] = "G"
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: ’Seq’ instance has no attribute ’__setitem__’
Jednak istnieje możliwość przekształcenia tej sekwencji w taką, w której można dokonywać zmian
(obiekt MutableSeq):
>>> zmienna_sek = moja_sek.tomutable()
>>> zmienna_sek
MutableSeq(’GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA’, IUPACUnambiguousDNA())
Można też stworzyć obiekt MutableSeq bezpośrednio z ciągu znaków:
>>> from Bio.Seq import MutableSeq
>>> from Bio.Alphabet import IUPAC
>>> zmienna_sek = MutableSeq("GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA",
IUPAC.unambiguous_dna)
Każdy z tych sposobów da w wyniku sekwencję, która może być modyfikowana:
>>> zmienna_sek
MutableSeq(’GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA’, IUPACUnambiguousDNA())
>>> zmienna_sek[5] = "T"
>>> zmienna_sek
MutableSeq(’GCCATTGTAATGGGCCGCTGAAAGGGTGCCCGA’, IUPACUnambiguousDNA())
>>> zmienna_sek.remove("T")
>>> zmienna_sek
MutableSeq(’GCCATGTAATGGGCCGCTGAAAGGGTGCCCGA’, IUPACUnambiguousDNA())
>>> zmienna_sek.reverse()
>>> zmienna_sek
MutableSeq(’AGCCCGTGGGAAAGTCGCCGGGTAATGTACCG’, IUPACUnambiguousDNA())
13
Zauważmy, że w przeciwieństwie do obiektu Seq, metody obiektu MutableSeq, takie jak
reverse.complement() i reverse() od razu zmieniają modyfikowaną sekwencję. Ponadto ważną
różnicą pomiędzy obiektami stałymi i zmiennymi w Pythonie jest to, że MutableSeq nie może być
używany jako klucz słownika w przeciwieństwie do ciągu znaków lub obiektu Seq. Po zakończeniu
edycji sekwencji można z powrotem zapisać ją jako nieedytowalny obiekt Seq:
>>> nowa_sek = zmienna_sek.toseq()
>>> nowa_sek
Seq(’AGCCCGTGGGAAAGTCGCCGGGTAATGTACCG’, IUPACUnambiguousDNA())
Istnieje też możliwość uzyskania ciągu znaków (string) z obiektu MutableSeq, tak jak ze zwykłego
obiektu Seq.
7.3 Obiekty UnknownSeq
Obiekty UnknownSeq stanowią podklasę podstawowego obiektu Seq, która służy do przetwarzania
sekwencji, dla których znamy długość, ale nie znamy wszystkich elementów ją tworzących. Można
oczywiście wykorzystać w tym celu zwykły obiekt Seq, ale przechowywanie w pamięci komputera
ciągu miliona znaków „N” (nieznana zasada) jest znacznie mniej praktyczne niż zapisanie „N” i
liczby całkowitej, mówiącej o liczbie nieznanych zasad.
>>> from Bio.Seq import UnknownSeq
>>> nieznana = UnknownSeq(20)
>>> nieznana
UnknownSeq(20, alphabet = Alphabet(), character = ’?’)
>>> print nieznana
????????????????????
>>> len(nieznana)
20
Istnieje też możliwość specyfikacji alfabetu dla podanej sekwencji, tak aby zamiast znaków „?”
pojawiły się „N” dla kwasów nukleinowych lub „X” dla białek:
>>> from Bio.Seq import UnknownSeq
>>> from Bio.Alphabet import IUPAC
>>> nieznany_dna = UnknownSeq(20, alphabet=IUPAC.ambiguous_dna)
>>> nieznany_dna
UnknownSeq(20, alphabet = IUPACAmbiguousDNA(), character = ’N’)
>>> print nieznany_dna
NNNNNNNNNNNNNNNNNNNN
Obiekt UnknownSeq może podlegać wszystkim tym modyfikacjom, co zwykły obiekt Seq, z tym że
wyniki tych modyfikacji zajmują znacznie mniej miejsca w pamięci komputera:
>>> nieznany_dna
UnknownSeq(20, alphabet = IUPACAmbiguousDNA(), character = ’N’)
>>> nieznany_dna.complement()
UnknownSeq(20, alphabet = IUPACAmbiguousDNA(), character = ’N’)
>>> nieznany_dna.reverse_complement()
UnknownSeq(20, alphabet = IUPACAmbiguousDNA(), character = ’N’)
>>> nieznany_dna.transcribe()
UnknownSeq(20, alphabet = IUPACAmbiguousRNA(), character = ’N’)
>>> nieznane_bialko = nieznany_dna.translate()
>>> nieznane_bialko
UnknownSeq(6, alphabet = ProteinAlphabet(), character = ’X’)
>>> print nieznane_bialko
14
XXXXXX
>>> len(nieznane_bialko)
6
7.4 Zadania
1. Napisz skrypt o nazwie porownywanie.py, który pozwoli na porównanie dwóch sekwencji
podanych przez użytkownika. Użytkownik podaje też rodzaj alfabetu dla każdej z dwóch
porównywanych sekwencji. Przykładowy rezultat działania:
Podaj pierwsza sekwencje do porownania: AAAGGGTTTAAA
Podaj alfabet dla pierwszej sekwencji: IUPAC.unambiguous_dna
Podaj druga sekwencje do porownania: AAAGGGTTTAAA
Podaj alfabet dla drugiej sekwencji: IUPAC.unambiguous_dna
Wynik porownania: True
2. Dla sekwencji: „TTTATTCACAATAGGAGGATTAACGGGAGTAGTTCTCGCAAACTCCTC
AATCGACATTATCCTACACGATACCTACTACG” utwórz obiekt MutableSeq, korzystając z
alfabetu IUPAC.unambiguous_dna. Następnie dokonaj następujących operacji na tej sekwencji:
podmień zasady na 5, 10, 15 i 20 miejscu na „C”, usuń pierwszą napotkaną zasadę A, odwróć tak
zmodyfikowaną sekwencję, a na koniec przekształć ją z powrotem na obiekt Seq.
3. Napisz skrypt o dowolnej nazwie tworzący obiekt UnknownSeq o parametrach zadanych przez
użytkownika (długość nieznanej sekwencji, typ alfabetu, symbol nieznanej zasady), a następnie
dokonujący transkrypcji i translacji tej sekwencji oraz podający długość wynikowych produktów.
Przykładowy rezultat:
Podaj dlugosc nieznanej sekwencji: 25
Podaj typ alfabetu: IUPAC.ambiguous_dna
Podaj symbol zasady: N
Nieznana sekwencja: NNNNNNNNNNNNNNNNNNNNNNNNN
mRNA: NNNNNNNNNNNNNNNNNNNNNNNNN
Dlugosc mRNA: 25
bialko: XXXXXXXX
Dlugosc bialka: 8
8 Bezpośrednia praca z ciągami znaków
Na koniec warto zaznaczyć, że zamiast pracować na obiektach Seq, UnknownSeq czy MutableSeq
istnieje możliwość pracy bezpośrednio na ciągach znaków (string). Importujemy wtedy z Bio.Seq
same funkcje:
>>> from Bio.Seq import reverse_complement, transcribe, back_transcribe, translate
>>> moj_lancuch = "GCTGTTATGGGTCGTTGGAAGGGTGGTCGTGCTGCTGGTTAG"
>>> reverse_complement(moj_lancuch)
’CTAACCAGCAGCACGACCACCCTTCCAACGACCCATAACAGC’
>>> transcribe(moj_lancuch)
’GCUGUUAUGGGUCGUUGGAAGGGUGGUCGUGCUGCUGGUUAG’
>>> back_transcribe(moj_lancuch)
’GCTGTTATGGGTCGTTGGAAGGGTGGTCGTGCTGCTGGTTAG’
>>> translate(moj_lancuch)
’AVMGRWKGGRAAG*’
9 Literatura:
Jeff Chang, Brad Chapman, Iddo Friedberg, Thomas Hamelryck, Michiel de Hoon, Peter Cock,
15
Tiago Antao, Eric Talevich, Bartek Wilczyński. Biopython. Tutorial and Cookbook. 2010. ss. 7-31.
16
Download