Solution

ID: past-exam-of-the-mathematical-and-computational-biology-course-of-the-university-of-cambridge/2024/paper-2/c8/b/solution

For each match state, count the nongap amino acids and divide by the number of nongap observations in that column. A gap is not one of the twenty emitted amino acids; including it in the denominator would make the emission probabilities sum to less than one:
def emission_counts(column):
    counts = Counter(str(x) for x in column if x != ".")
    n = sum(counts.values())
    if n == 0:
        raise ValueError("an all-gap column has no empirical emission distribution")
    return counts, n

match_emissions = {}
for state, j in enumerate(match_columns, 1):
    counts, n = emission_counts(A[:, j])
    match_emissions[state] = {aa: count/n for aa, count in counts.items()}
    print(state, j+1, match_emissions[state])
The table gives an exact compact representation of every emission probability: divide each displayed count by the denominator in its row; all unlisted amino acids have probability zero. The state number follows the order of match states, while the column refers to the original multiple sequence alignment.
StateAlignment columnNongap counts
119I:1, K:1, R:1, S:2, V:3, Y:1
229D:1, E:2, G:1, I:1, L:1, Q:2, S:1
339E:2, I:1, K:1, Q:1, R:3, T:1
449L:8, M:1
559E:3, G:1, L:2, N:1, Q:1, S:1
669A:1, D:2, G:1, K:1, N:1, S:2, T:1
779A:1, E:3, I:2, L:1, M:1, V:1
889I:2, L:7
999D:3, E:1, K:1, L:2, N:1, Q:1
10109D:1, E:3, G:1, N:1, P:1, S:2
11119A:5, D:1, G:1, P:1, T:1
12129I:1, L:7, Y:1
13139E:1, F:1, G:1, H:2, M:1, Q:2, T:1
14149F:9
15159F:1, L:8
16169E:1, I:1, L:1, N:3, Q:1, R:1, Y:1
17179D:6, E:2, S:1
18189C:7, F:1, S:1
19199K:1, N:6, R:2
20209E:1, F:1, I:5, L:1, V:1
21219K:3, P:1, Q:1, S:4
22297K:4, P:1, R:1, S:1
23307E:2, F:1, G:1, I:1, K:1, V:1
24317D:3, E:1, G:1, K:1, S:1
25328D:1, E:1, G:1, K:1, N:1, R:3
26338D:7, N:1
27348A:1, P:6, S:1
28359C:1, H:1, I:1, K:1, M:1, R:1, T:3
29369E:1, F:1, G:1, L:1, Q:3, W:1, Y:1
30379I:5, L:1, T:2, Y:1
31389A:1, G:1, P:3, S:4
32399I:1, K:6, L:1, R:1
33409F:1, N:1, Q:4, T:2, V:1
34419A:1, F:1, I:1, V:6
35429I:1, L:7, V:1
36439A:1, C:1, E:1, N:1, R:1, S:3, V:1
37449D:3, E:5, Q:1
38459A:1, C:7, I:1
39469K:2, L:3, R:4
40479A:3, E:1, L:1, N:3, T:1
41489I:4, L:1, T:1, V:3
42499L:9
43509D:1, E:1, H:1, Q:1, S:1, T:1, V:1, Y:2
44519E:1, K:1, Q:2, R:1, V:4
45529L:9
46539G:9
47549P:8, T:1
48559W:9
49569A:2, C:7
50579A:6, C:1, L:1, T:1
51589A:1, D:3, F:1, S:2, V:1, Y:1
52599K:4, R:2, S:3
53609A:2, F:1, I:2, L:2, V:2
54619A:7, G:1, Y:1
55629E:3, G:3, Q:3
56639I:3, M:3, T:1, Y:2
57649F:3, L:2, M:3, N:1
58659H:1, I:3, L:1, V:4
59669K:1, M:1, P:1, R:4, S:1, T:1
60679D:1, E:3, Q:4, Y:1
61689I:1, L:7, M:1
62699D:1, E:4, Q:4
63709K:7, R:2
64719A:1, I:2, M:1, N:1, R:1, Y:3
65729A:1, C:1, D:1, E:2, I:2, V:2
66739K:9
67749H:4, L:1, Q:2, S:1, V:1
68759E:8, Q:1
69769Q:3, R:1, S:2, T:3
70779C:2, E:3, G:1, R:1, S:1, V:1
71789A:1, D:2, E:3, I:1, K:1, Y:1
72799I:2, L:3, M:1, N:1, Q:1, V:1
These are unregularized maximum-likelihood estimates of the emission probabilities. No additional artificial observations are added. Although only emissions are requested here, a full profile hidden Markov model would also require transitions and deletion mechanisms to represent the gaps that remain in some match columns.

New to topics? Read the docs here!