code: def count_mutations(codon, AA, alleles, counts, nucs, trans_table):
      
      # find alternative codons based on SNPs
      obs_codons = [] # codons observed from SNPs
      for pos, pos_mutations in enumerate(alleles):
          mutations = [b for b in pos_mutations if b in nucs]
          for mutation in mutations:
              alt_codon = codon[:]
              alt_codon[pos] = mutation
              obs_codons.append(alt_codon)
      obs_codons = [i for i in obs_codons if i != codon]
      obs_AAs = [codon2aa(i, trans_table) for i in obs_codons]
      obs_AAs = [i for i in obs_AAs if i != AA]
      num_mutations = len(obs_codons)
      num_nonSyn    = len(obs_AAs)
      num_syn       = num_mutations - num_nonSyn
      counts['obs syn']     += num_syn
      counts['obs non-syn'] += num_nonSyn
      # find all possible alternative codons based on single base changes
      pos_codons = [] # codons inferred from all possible SNPs
      for pos in range(0, 3):
          for nuc in nucs:
              pos_codon = codon[:]
              pos_codon[pos] = nuc
              pos_codons.append(pos_codon)
      pos_codons = [i for i in pos_codons if i != codon]
      pos_AAs = [codon2aa(i, trans_table) for i in pos_codons]
      pos_AAs = [i for i in pos_AAs if i != AA]
      num_mutations = len(pos_codons)
      num_nonSyn    = len(pos_AAs)
      num_syn       = num_mutations - num_nonSyn
      counts['pos syn']     += num_syn
      counts['pos non-syn'] += num_nonSyn
      return counts
docs: count types of mutations in codon
      counts = {'obs syn':#, 'pos syn':#, 'obs non-syn':#, 'pos non-syn':#}