Return a list of codons that would be translated to the given protein 
    sequence.  Codons are picked first to minimize the mutations relative to a 
    template DNA sequence and second to prefer "optimal" codons.

def make_codon_list(protein_seq, template_dna=None, include_stop=True):
    """
    Return a list of codons that would be translated to the given protein 
    sequence.  Codons are picked first to minimize the mutations relative to a 
    template DNA sequence and second to prefer "optimal" codons.
    """

    codon_list = []

    if template_dna is None:
        template_dna = []

    # Reverse translate each codon, preferring (in order):
    # 1. The codon with the most similarity to the template codon.
    # 2. The codon with the highest natural usage.

    for i, res in enumerate(protein_seq.upper()):
        try: template_codon = template_dna[3*i:3*i+3]
        except IndexError: template_codon = '---'

        # Already sorted by natural codon usage
        possible_codons = dna.ecoli_reverse_translate[res]

        # Sort by similarity.  Note that this is a stable sort.
        possible_codons.sort(
                key=lambda x: dna.num_mutations(x, template_codon))

        # Pick the best codon.
        codon_list.append(possible_codons[0])

    # Make sure the sequence ends with a stop codon.
    last_codon = codon_list[-1]
    stop_codons = dna.ecoli_reverse_translate['.']

    if include_stop and last_codon not in stop_codons:
        codon_list.append(stop_codons[0])

    return codon_list