From Gene to Protein

Genetics and Heredity Fundamentals

Course 1 ยท Chapter 3 ยท From Gene to Protein

Genetics and Heredity Fundamentals 2 described a gene as a stretch of DNA that carries instructions. This chapter follows those instructions to the product: a protein, a chain of smaller units called amino acids, whose shape lets it do a job in the cell. The route has two steps, and both are a kind of text processing, which makes them easy to write as Python 3 programs.

What was run, and what was not
Every program in this chapter was run and the output shown is what it printed. The biology is written from general knowledge; items marked (check) are the ones to verify first.

Two Steps: Transcription and Translation

The DNA stays put (in plants and animals, inside the nucleus). To use a gene, the cell first makes a working copy in a related molecule, RNA. This copying is transcription. RNA differs from DNA in three ways that matter here: it is usually a single strand, its sugar is different, and it uses the base U (uracil) where DNA uses T. The copy is built by the pairing rules of chapter 2, so it matches the coding strand of the gene letter for letter, with U in place of T.

The RNA message is then read by cell machinery called the ribosome, which builds the protein one amino acid at a time. This reading is translation. The message is read in blocks of three bases, called codons, and each codon names one amino acid.

StepFromToUnit
TranscriptionDNARNAone base at a time (T becomes U)
TranslationRNAproteinone codon (three bases) per amino acid

Real cells add steps that this chapter skips. In plants and animals the first RNA copy is often trimmed before use, with some stretches removed (check), and the beginning and end of a message have extra features. We will write the central idea and leave those details aside.

The Codon Table as Code

Three bases, four choices each, gives 4 x 4 x 4 = 64 codons. Sixty-one of them name one of the 20 standard amino acids; three are stop codons that end the message (UAA, UAG and UGA; check). One codon, AUG, names the amino acid methionine and also usually marks where reading begins (check).

Rather than typing 64 entries, we can write the table as one string of 64 letters in a fixed order and build the dictionary with loops. The order is T, C, A, G for each of the three positions, and each letter is the one-letter code for an amino acid, with * meaning stop. We work with the DNA letters (T), since our genes are written as DNA. The one-letter amino acid codes and the table itself are written from general knowledge (check), which is why the program also tests the table against facts we know.

B = "TCAG" AA = "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG" CODON = {a + b + c: AA[16 * i + 4 * j + k] for i, a in enumerate(B) for j, b in enumerate(B) for k, c in enumerate(B)} def transcribe(dna): return dna.replace("T", "U") def translate(dna): protein = [] for i in range(0, len(dna) - 2, 3): aa = CODON[dna[i:i + 3]] if aa == "*": break protein.append(aa) return "".join(protein) gene = "ATGGCCTTGAAATGGTAA" print(transcribe(gene)) print(translate(gene)) print(len(CODON), list(CODON.values()).count("*"), len(set(CODON.values()) - {"*"}))
AUGGCCUUGAAAUGGUAA MALKW 64 3 20

The gene is six codons: ATG GCC TTG AAA TGG TAA. The first five name M, A, L, K and W; the sixth is a stop, so translate halts and the protein is MALKW, five amino acids long. The last line confirms the counts above: 64 codons, 3 of them stops, 20 amino acids. (The sequence itself is invented for the example, not a real gene.)

One Code, Many Spellings

There are 61 codons but only 20 amino acids, so most amino acids have more than one codon. The code is said to be degenerate (or redundant): several codons, called synonymous, name the same amino acid. This is not ambiguity, because each codon still names exactly one amino acid. Let us count how many codons each amino acid has.

from collections import Counter sizes = Counter(CODON.values()) print(sizes["L"], sizes["R"], sizes["S"], sizes["M"], sizes["W"]) print(Counter(sizes[a] for a in sizes if a != "*")) print(CODON["CTT"], CODON["CTC"], CODON["CTA"], CODON["CTG"])
6 6 6 1 1 Counter({2: 9, 4: 5, 6: 3, 1: 2, 3: 1}) L L L L

Three amino acids (L, R, S) have six codons each, and two (M and W) have only one. Reading the second line as "how many amino acids have this many codons": nine have two, five have four, three have six, two have one, and one (I) has three. The third line shows a common pattern: the four codons CTN all name L, so a change in the third base often changes nothing. That pattern is why the next section matters.

Mutations

A mutation is a change in the DNA sequence. Most that matter for a protein fall into a few kinds, and they can be told apart by comparing the protein before and after:

KindWhat changes in the DNAEffect on the protein
Silentone base swappednone: the new codon names the same amino acid
Missenseone base swappedone amino acid replaced by another
Nonsenseone base swappeda stop codon appears early; the protein is cut short
Frameshiftbases inserted or deleted, not a multiple of threeevery codon after the change is read differently
In-frame indela multiple of three bases inserted or deletedamino acids added or lost; the rest is unchanged

The one-base swaps are called point mutations (or substitutions). We can classify a change automatically by translating both versions and comparing them.

def classify(old, new): if len(old) != len(new): return "frameshift" if (len(new) - len(old)) % 3 else "in-frame indel" a, b = translate(old), translate(new) if a == b: return "silent" return "nonsense" if len(b) < len(a) else "missense" cases = { "original": gene, "G>T at 9": gene[:8] + "T" + gene[9:], "C>G at 6": gene[:5] + "G" + gene[6:], "G>A at 14": gene[:13] + "A" + gene[14:], "delete base 5": gene[:4] + gene[5:], "insert GGG": gene[:6] + "GGG" + gene[6:], } for label, seq in cases.items(): print(f"{label:14} {translate(seq):8} {classify(gene, seq) if seq != gene else ''}")
original MALKW G>T at 9 MAFKW missense C>G at 6 MALKW silent G>A at 14 MALK nonsense delete base 5 MA frameshift insert GGG MAGLKW in-frame indel

Positions are counted from 1. Changing the ninth base turns TTG (L) into TTT (F): one amino acid replaced. Changing the sixth turns GCC into GCG, which still names A: silent. Changing the fourteenth turns TGG (W) into TAG, a stop, so the protein loses its last amino acid. Deleting one base shifts the reading frame, so the later codons are read in a different grouping; here the new message hits a stop early and the protein is just MA. Inserting three bases adds exactly one amino acid (G) and leaves the rest alone.

Silent does not always mean harmless
"Silent" only means the amino acid is unchanged. Some silent changes can still affect how a gene is used (check), and a "missense" change can range from harmless to serious depending on which amino acid is swapped and where. Our classifier counts changes; it does not judge their effect.

A Famous Single-Letter Change

The textbook example of a missense mutation is sickle cell disease, in which one base change in the gene for part of haemoglobin swaps the sixth amino acid from glutamic acid (E) to valine (V) (check). Below is the beginning of the normal sequence, in the form usually quoted (check, and note that the leading methionine is often removed in the finished protein), together with a changed version. We also try some other changes to the same stretch.

orig = "GTGCACCTGACTCCTGAGGAGAAG" variants = [("substitution", orig[:15] + "GTG" + orig[18:]), ("delete 1", orig[:15] + orig[16:]), ("insert 3", orig[:15] + "AAA" + orig[15:]), ("stop", orig[:15] + "TAG" + orig[18:])] for label, mut in variants: print(label, translate(orig), "->", translate(mut), classify(orig, mut))
substitution VHLTPEEK -> VHLTPVEK missense delete 1 VHLTPEEK -> VHLTPRR frameshift insert 3 VHLTPEEK -> VHLTPKEEK in-frame indel stop VHLTPEEK -> VHLTP nonsense

The first variant changes one letter, GAG to GTG, and one amino acid: the sixth letter of the protein goes from E to V, the change described above. The frameshift garbles everything after the deletion, the three-base insertion adds one amino acid, and the stop variant ends the protein after five. Note how little the DNA changed in the first case: one base in 24, yet a different protein.

Challenges

Exercise 1

Write find_orfs(dna), which returns a list of (start, protein) pairs for every ATG that is followed, in the same frame, by a stop codon (use the codon table from this chapter; positions count from 0). Test it on ATGAAATTTGGGTAA, ATGTGGTGA and GGATGCCCTAGATGAAATAG.

๐Ÿ“„ View solution
Exercise 2

For the gene ATGGCCTTGAAATGGTAA, change each of the first 15 bases (the five codons before the stop) to each of the three other bases. Classify all 45 resulting mutations and count how many are silent, missense and nonsense.

๐Ÿ“„ View solution
Exercise 3

Write report(orig, mut) that prints the original protein, the mutated protein and the mutation kind, and also the position (counting from 1) of the first amino acid that differs, or none if the proteins are identical. Run it on four variants of the sequence GTGCACCTGACTCCTGAGGAGAAG.

๐Ÿ“„ View solution

Quick Reference

  • Transcription: DNA to RNA, with U in place of T
  • Translation: RNA read in codons of three bases, each naming one amino acid
  • Codon table: 64 codons; 61 name 20 amino acids, 3 are stops; the code is redundant but never ambiguous
  • Silent / missense / nonsense: same amino acid / different amino acid / early stop
  • Frameshift: insertion or deletion not a multiple of three; in-frame indel: a multiple of three
  • Check: the codon table string, the stop codons, the sickle cell details, skipped steps such as trimming of RNA
Coming next
Genetics and Heredity Fundamentals 4 looks at how cells divide and how sex cells are made, and why brothers and sisters differ.