def ReadCodonAlignment(fastafile, checknewickvalid):
codonmatch = re.compile('<STR_LIT>')<EOL>gapmatch = re.compile('<STR_LIT>')<EOL>seqs = [(seq.description.strip(), str(seq.seq).upper()) for seq<EOL>in Bio.SeqIO.parse(fastafile, '<STR_LIT>')]<EOL>assert seqs, "<STR_LIT>".format(fastafile)<EOL>seqlen = len(seqs[<NUM_LIT:0>][<NUM_LIT:1>])<EOL>if not all([len(seq) == seqlen for (head, seq) in seqs]):<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(fastafile))<EOL><DEDENT>if (seqlen < <NUM_LIT:3>) or (seqlen % <NUM_LIT:3> != <NUM_LIT:0>):<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>).format(fastafile, seqlen))<EOL><DEDENT>terminalcodon = []<EOL>codons_by_position = dict([(icodon, []) for icodon in range(seqlen // <NUM_LIT:3>)])<EOL>for (head, seq) in seqs:<EOL><INDENT>assert len(seq) % <NUM_LIT:3> == <NUM_LIT:0><EOL>for icodon in range(seqlen // <NUM_LIT:3>):<EOL><INDENT>codon = seq[<NUM_LIT:3> * icodon : <NUM_LIT:3> * icodon + <NUM_LIT:3>]<EOL>codons_by_position[icodon].append(codon)<EOL>if codonmatch.search(codon):<EOL><INDENT>aa = str(Bio.Seq.Seq(codon).translate())<EOL>if aa == '<STR_LIT:*>':<EOL><INDENT>if icodon + <NUM_LIT:1> != len(seq) // <NUM_LIT:3>:<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(<EOL>fastafile, head, icodon + <NUM_LIT:1>, codon))<EOL><DEDENT><DEDENT><DEDENT>elif codon == '<STR_LIT>':<EOL><INDENT>aa = '<STR_LIT:->'<EOL><DEDENT>else:<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(fastafile, head, icodon + <NUM_LIT:1>, codon))<EOL><DEDENT><DEDENT>terminalcodon.append(aa)<EOL><DEDENT>for (icodon, codonlist) in codons_by_position.items():<EOL><INDENT>if all([codon == '<STR_LIT>' for codon in codonlist]):<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>).format(fastafile, icodon + <NUM_LIT:1>))<EOL><DEDENT><DEDENT>if all([aa in ['<STR_LIT:*>', '<STR_LIT:->'] for aa in terminalcodon]):<EOL><INDENT>if len(seq) == <NUM_LIT:3>:<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(fastafile))<EOL><DEDENT>seqs = [(head, seq[ : -<NUM_LIT:3>]) for (head, seq) in seqs]<EOL><DEDENT>elif any([aa == '<STR_LIT:*>' for aa in terminalcodon]):<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(fastafile))<EOL><DEDENT>if any([gapmatch.search(seq) for (head, seq) in seqs]):<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(fastafile))<EOL><DEDENT>if checknewickvalid:<EOL><INDENT>if len(set([head for (head, seq) in seqs])) != len(seqs):<EOL><INDENT>raise ValueError("<STR_LIT>".format(fastafile))<EOL><DEDENT>disallowedheader = re.compile('<STR_LIT>')<EOL>for (head, seq) in seqs:<EOL><INDENT>if disallowedheader.search(head):<EOL><INDENT>raise ValueError(("<STR_LIT>"<EOL>"<STR_LIT>").format(fastafile, head))<EOL><DEDENT><DEDENT><DEDENT>return seqs<EOL>
Reads codon alignment from file.

    *fastafile* is the name of an existing FASTA file.

    *checknewickvalid* : if *True*, we require that names are unique and do
    **not** contain spaces, commas, colons, semicolons, parentheses, square
    brackets, or single or double quotation marks.
    If any of these disallowed characters are present, raises an Exception.

    Reads the alignment from the *fastafile* and returns the aligned
    sequences as a list of 2-tuple of strings *(header, sequence)*
    where *sequence* is upper case.

    If the terminal codon is a stop codon for **all** sequences, then
    this terminal codon is trimmed. Raises an exception if the sequences
    are not aligned codon sequences that are free of stop codons (with
    the exception of a shared terminal stop) and free of ambiguous nucleotides.

    Read aligned sequences in this example:

    >>> seqs = [('seq1', 'ATGGAA'), ('seq2', 'ATGAAA')]
    >>> f = io.StringIO()
    >>> n = f.write(u'\\n'.join(['>{0}\\n{1}'.format(*tup) for tup in seqs]))
    >>> n = f.seek(0)
    >>> a = ReadCodonAlignment(f, True)
    >>> seqs == a
    True

    Trim stop codons from all sequences in this example:

    >>> seqs = [('seq1', 'ATGTAA'), ('seq2', 'ATGTGA')]
    >>> f = io.StringIO()
    >>> n = f.write(u'\\n'.join(['>{0}\\n{1}'.format(*tup) for tup in seqs]))
    >>> n = f.seek(0)
    >>> a = ReadCodonAlignment(f, True)
    >>> [(head, seq[ : -3]) for (head, seq) in seqs] == a
    True

    Read sequences with gap:

    >>> seqs = [('seq1', 'ATG---'), ('seq2', 'ATGAGA')]
    >>> f = io.StringIO()
    >>> n = f.write(u'\\n'.join(['>{0}\\n{1}'.format(*tup) for tup in seqs]))
    >>> n = f.seek(0)
    >>> a = ReadCodonAlignment(f, True)
    >>> [(head, seq) for (head, seq) in seqs] == a
    True

    Premature stop codon gives error:

    >>> seqs = [('seq1', 'TGAATG'), ('seq2', 'ATGAGA')]
    >>> f = io.StringIO()
    >>> n = f.write(u'\\n'.join(['>{0}\\n{1}'.format(*tup) for tup in seqs]))
    >>> n = f.seek(0)
    >>> a = ReadCodonAlignment(f, True) # doctest: +IGNORE_EXCEPTION_DETAIL
    Traceback (most recent call last):
    ValueError: