In the code below there is a dictionary (named codon_table
) in which keys represent codons and values represent corresponding amino acids.
Write a program that will translate a DNA sequence into an amino acid sequence using the codons disctionary. Print out the result. Note that *
are stop codons.
If you want to know more about how the codons dictionary was created, read the documentation for list comprehension and the built-in zip-function.
# Create codons dictionary
bases = ['t', 'c', 'a', 'g']
codons = [a+b+c for a in bases for b in bases for c in bases]
amino_acids = 'FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG'
codon_table = dict(zip(codons, amino_acids))
DNA = 'atgattccaacgcgaaggtcaagtacgtacagctctcagtgtgtgctactcaccgactccgtcatagcaaccggcgtcgtggtcgttaccattgcataa'
# translate the sequence
prot = ""
for i in range(0,len(DNA) - 2,3):
codon = DNA[i:i+3]
amino_acid = codon_table[codon]
prot = prot + amino_acid
print(prot)
MIPTRRSSTYSSQCVLLTDSVIATGVVVVTIA*
a) Write a function that receives an amino acid sequence as string and returns a dictionary where the keys are the amino acid residues and the values are the number of times each residue appeared in the protein. For example, the expected result for the peptide LLTDSGT
is: {'L': 2, 'T': 2, 'D': 1, 'S': 1, 'G': 1}
.
Test your function on the provided sequences, and print the results in the following format:
L - 2
T - 2
D - 1
S - 1
G - 1
Remember: dict
is unordered.
def count_residues(protein_seq):
counts_dict = {} # create an empty dictionary to store results
for aa in protein_seq:
# if amino acid has already been added to the dictionary, increase its count by 1
if aa in counts_dict:
counts_dict[aa] += 1
# if amino acid found for the first time, add it with count 1
else:
counts_dict[aa] = 1
return counts_dict
protein_sequence = 'DQHTWMYAEGYLNHVYRCDKQRAEDKECNGLYAWALALESHGKGSYYCQGFKTFPNPWPMHMMTFVMADLYQYMEI'
aa_counts_dict = count_residues(protein_sequence)
# print results
for aa in aa_counts_dict:
print(aa,'-',aa_counts_dict[aa])
F - 3 W - 3 H - 4 I - 1 K - 4 Q - 4 P - 3 L - 5 G - 5 N - 3 A - 6 E - 5 C - 3 D - 4 Y - 8 V - 2 R - 2 S - 2 T - 3 M - 6
b) Write a function that receives an amino acid sequence as a string and returns a dictionary with the frequencies of hydrophobic, posituvely-charged, negatively-charged, polar an other amino acids. Use the strings provided in the code below.
For example,
residues_type_frequencies('LLTDSGT')
{'hydrophobic': 0.286, 'positive': 0, 'negative': 0.143, 'polar': 0.428, 'other': 0.143}
Test your function on the provided amino acid sequence, and print the results in the following format:
hydrophobic - 0.286
positive - 0
negative - 0.143
polar - 0.428
other - 0.143
def residues_type_frequencies(protein_seq):
hydrophobic = ['A','V','I','L','M','F','Y','W']
pos_charged = ['R','H','K']
neg_charged = ['D','E']
polar = ['S','T','N','Q']
other = ['C','U','G','P']
prot_length = len(protein_seq)
aa_types_dict = {'hydrophobic': 0, 'positive': 0, 'negative': 0, 'polar': 0, 'other': 0}
# first, count amino acids in each category
for aa in protein_seq:
if aa in hydrophobic:
aa_types_dict['hydrophobic'] += 1
elif aa in pos_charged:
aa_types_dict['positive'] += 1
elif aa in neg_charged:
aa_types_dict['negative'] += 1
elif aa in polar:
aa_types_dict['polar'] += 1
elif aa in other:
aa_types_dict['other'] += 1
# now, convert to frequencies
for aa_type in aa_types_dict:
aa_types_dict[aa_type] = aa_types_dict[aa_type]/prot_length
return aa_types_dict
protein_sequence = 'DQHTWMYAEGYLNHVYRCDKQRAEDKECNGLYAWALALESHGKGSYYCQGFKTFPNPWPMHMMTFVMADLYQYMEI'
aa_types_freq_dict = residues_type_frequencies(protein_sequence)
# print results
for aa_type in aa_types_freq_dict:
print(aa_type,'-',aa_types_freq_dict[aa_type])
other - 0.14473684210526316 polar - 0.15789473684210525 negative - 0.11842105263157894 positive - 0.13157894736842105 hydrophobic - 0.4473684210526316
A palindromic sequence is a DNA sequence that is the same whether read 5' to 3' on one strand or 5' to 3' on the complementary strand. For example, the sequence 5' GAATTC 3' is palindromic, since the complement strand is 3' CTTAAG 5', or 5' GAATTC 3'.
Palindromic sequences are biologically interesting because they can form special structural motifs, such as hairpins, and often are cutting sites for restriction enzymes.
a) Write a function is_palindrome
that receives a DNA sequence as a string and returns True
if it is palindromic and False
otherwise. You may use the function defined in the lecture to find the complement strand. The assertions test your function on the provided sequences.
def complement(sequence):
transcript_dict = {'A': 'T', 'T': 'A', 'G': 'C', 'C': 'G'}
complement = ''
for base in sequence:
complement += transcript_dict[base]
return complement
def reverse_sequence(sequence):
reversed_seq = ''
seq_as_list = list(sequence)
for base in reversed(seq_as_list):
reversed_seq += base
return reversed_seq
def reverse_complement(sequence):
complement_seq = complement(sequence)
reverse_complement = reverse_sequence(complement_seq)
return reverse_complement
def is_palindrome(seq):
if seq == reverse_complement(seq):
return True
else:
return False
assert(is_palindrome('GAATTC'))
assert(is_palindrome('GATATC'))
assert(is_palindrome('AGCTTCTAGTCGACTAGAAGCT'))
assert(not is_palindrome('GAACTC'))
assert(not is_palindrome('GATATG'))
b) Now use the function is_palindrome
to look for palindromic subsequences within a given DNA sequence.
Write a function find_palindromes
that receives two parameters: a sequence seq
(string) and an integer n
. The function searches seq
for n bases long palindromic subsequences. It returns a list of all the palindromic subsequences found. If none were found, it return an empty list. Implement the function using a for loop.
def find_palindromes(S, n):
palindromes = []
i = 0
for i in range(0,len(S)-n+1):
subseq = S[i:i+n]
if is_palindrome(subseq):
palindromes.append(subseq)
return palindromes
DNA_seq = 'GGAGCTCCCAAAGCCATCAATATTCATCAAAACGAATTCAACGGAGCTCGATATCGCATCGCAAAAGACACC'
palindromic_sequences = find_palindromes(DNA_seq,6)
assert palindromic_sequences == ['GAGCTC', 'AATATT', 'GAATTC', 'GAGCTC', 'GATATC']
c) Implement the same function using a while loop.
def find_palindromes(S, n):
palindromes = []
i = 0
while i < len(S)-n+1:
subseq = S[i:i+n]
if is_palindrome(subseq):
palindromes.append(subseq)
i += 1
return palindromes
DNA_seq = 'GGAGCTCCCAAAGCCATCAATATTCATCAAAACGAATTCAACGGAGCTCGATATCGCATCGCAAAAGACACC'
palindromic_sequences = find_palindromes(DNA_seq,6)
assert palindromic_sequences == ['GAGCTC', 'AATATT', 'GAATTC', 'GAGCTC', 'GATATC']
A major caveat of the functions created so far is that they will return all palindromic sequences, even if they are overlapping, which makes no biological sense. For example, if we search the sequence GAATTCGAACAT
for 6-bases long palindromes, we will get both GAATTC
and TTCGAA
, although they are overlapping.
d) Choose one of the implementations from parts b and c, and change it so that no overlapping palindromes will be found. The function should return the upstream palindromes where there is an overlap.
def find_palindromes_no_overlap(S, n):
palindromes = []
i = 0
while i < len(S)-n+1:
subseq = S[i:i+n]
if is_palindrome(subseq):
palindromes.append(subseq)
i += n
else:
i += 1
return palindromes
# test
DNA_seq = 'GGAGCTCCCAAAGCCATCAATATTCATCAAAACGAATTCAACGGAGCTCGATATCGCATCGCAAAAGACACC'
palindromic_sequences = find_palindromes_no_overlap(DNA_seq,6)
assert palindromic_sequences == ['GAGCTC', 'AATATT', 'GAATTC', 'GAGCTC', 'GATATC']
DNA_seq = 'GGAGCTCCCAAAGCCATCAGAATTCGAACATATCGCAAAAGACACC'
palindromic_sequences = find_palindromes(DNA_seq,6)
assert palindromic_sequences == ['GAGCTC', 'GAATTC', 'TTCGAA']
DNA_seq = 'GGAGCTCCCAAAGCCATCAGAATTCGAACATATCGCAAAAGACACC'
palindromic_sequences = find_palindromes_no_overlap(DNA_seq,6)
assert palindromic_sequences == ['GAGCTC', 'GAATTC']