Step by step
Think about what is is you need to do. From the dictionaries exercise you know how to count letters in a string using a dictionary. What you need to do here is similar, but here you have an extra layer of dictionaries.
After "uppercasing" orf you can call splitCodons(orf) to get a list of the codons in the ORF. You then loop over the codons, translate each codon into an amino acid aa using translateCodon(codon). Then if your top dictionary is D you can count your codons this way:
D[aa][codon] += 1
but before doing so you need to check each time if the top dictionary has the aa key and if the nested one have the codon key. If not you need to make them and set the value of the latter to 0.
Your dictionary should not include amino acids that are not in the ORF, but you want all the possible codons for each amino acid represented in your nested dictionaries. Your result would not correctly represent codon bias if the codons that where not used was not included. We include the codons that we did not see in the ORF by looping over the exerciseWeek4.aminoAcidMap like this:
for codon, aa in exerciseWeek4.aminoAcidMap.items():
and then if aa is in your top dictionary and if codon is not in corresponding nested dictionary you set D[aa][codon] = 0.0.
Finally you need to normalize the counts so they become frequencies (i.e. count/total). To do that you need to loop over the keys in the top dictionary, and use each key to retrieve all the counts for that amino acid, and sum them: nrCodons = sum(D[aa].values()). Then use a nested for loop (a for loop within the for loop) to loop over the keys (the codons) of corresponding nested dictionary. In that nested for loop you can then divide each count by the total number of codons for that amino acid:
D[aa][codon] /= float(nrCodons)
All the remains then is to return the finished dictionary.