
:>"^K4                 @   s   d  Z  d d l m Z d d l Z d d l m Z d d l m Z d d l m	 Z	 d d l
 m Z d d	 l
 m Z e j d
  Z e j d  Z d Z d d   Z Gd d   d e  Z Gd d   d e  Z d S)a  Bio.AlignIO support for "xmfa" output from Mauve/ProgressiveMauve.

You are expected to use this module via the Bio.AlignIO functions (or the
Bio.SeqIO functions if you want to work directly with the gapped sequences).

For example, consider a progressiveMauve alignment file containing the following::

    #FormatVersion Mauve1
    #Sequence1File	a.fa
    #Sequence1Entry	1
    #Sequence1Format	FastA
    #Sequence2File	b.fa
    #Sequence2Entry	2
    #Sequence2Format	FastA
    #Sequence3File	c.fa
    #Sequence3Entry	3
    #Sequence3Format	FastA
    #BackboneFile	three.xmfa.bbcols
    > 1:0-0 + a.fa
    --------------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    --------------------------------------------------------------------------------
    > 2:5417-5968 + b.fa
    TTTAAACATCCCTCGGCCCGTCGCCCTTTTATAATAGCAGTACGTGAGAGGAGCGCCCTAAGCTTTGGGAAATTCAAGC-
    --------------------------------------------------------------------------------
    CTGGAACGTACTTGCTGGTTTCGCTACTATTTCAAACAAGTTAGAGGCCGTTACCTCGGGCGAACGTATAAACCATTCTG
    > 3:9476-10076 - c.fa
    TTTAAACACCTTTTTGGATG--GCCCAGTTCGTTCAGTTGTG-GGGAGGAGATCGCCCCAAACGTATGGTGAGTCGGGCG
    TTTCCTATAGCTATAGGACCAATCCACTTACCATACGCCCGGCGTCGCCCAGTCCGGTTCGGTACCCTCCATGACCCACG
    ---------------------------------------------------------AAATGAGGGCCCAGGGTATGCTT
    =
    > 2:5969-6015 + b.fa
    -----------------------
    GGGCGAACGTATAAACCATTCTG
    > 3:9429-9476 - c.fa
    TTCGGTACCCTCCATGACCCACG
    AAATGAGGGCCCAGGGTATGCTT

This is a multiple sequence alignment with multiple aligned sections, so you
would probably load this using the Bio.AlignIO.parse() function:

    >>> from Bio import AlignIO
    >>> align = AlignIO.parse("Mauve/simple_short.xmfa", "mauve")
    >>> alignments = list(align)
    >>> for aln in alignments:
    ...     print(aln)
    ...
    SingleLetterAlphabet() alignment with 3 rows and 240 columns
    --------------------------------------------...--- a.fa
    TTTAAACATCCCTCGGCCCGTCGCCCTTTTATAATAGCAGTACG...CTG b.fa/5416-5968
    TTTAAACACCTTTTTGGATG--GCCCAGTTCGTTCAGTTGTG-G...CTT c.fa/9475-10076
    SingleLetterAlphabet() alignment with 2 rows and 46 columns
    -----------------------GGGCGAACGTATAAACCATTCTG b.fa/5968-6015
    TTCGGTACCCTCCATGACCCACGAAATGAGGGCCCAGGGTATGCTT c.fa/9428-9476

Additional information is extracted from the XMFA file and available through
the annotation attribute of each record::

    >>> for record in alignments[0]:
    ...     print(record.id, len(record))
    ...     print("  start: %d, end: %d, strand: %d" %(
    ...         record.annotations['start'], record.annotations['end'],
    ...         record.annotations['strand']))
    ...
    a.fa 240
      start: 0, end: 0, strand: 1
    b.fa/5416-5968 240
      start: 5416, end: 5968, strand: 1
    c.fa/9475-10076 240
      start: 9475, end: 10076, strand: -1

    )print_functionN)Seq)	SeqRecord)MultipleSeqAlignment   )AlignmentIterator)SequentialAlignmentWriterzG> (?P<id>\d+):(?P<start>\d+)-(?P<end>\d+) (?P<strand>[+-]) (?P<name>.*)z]> (?P<id>\d+):(?P<start>\d+)-(?P<end>\d+) (?P<strand>[+-]) (?P<name>[^#]*) # (?P<realname>.*)z9> {seq_name}:{start}-{end} {strand} {file} # {ugly_hack}
c             C   sP   |  j  d  \ } } } t t | j  d   \ } } | d 8} | | | | f S)zDReturn (name, start, end) string tuple from an identifier (PRIVATE).:-r   )splitmapint)Z
identifieridlocstrandstartend r   8/tmp/pip-build-ww9dw3qa/biopython/Bio/AlignIO/MauveIO.py_identifier_splitc   s    
r   c                   sC   e  Z d  Z d Z   f d d   Z d d   Z d d d  Z   S)	MauveWriterzMauve/XMFA alignment writer.c                s/   t  t |   j | |   d |  _ d |  _ d S)zInitialize.FN)superr   __init___wrote_header_wrote_first)selfargskwargs)	__class__r   r   r   n   s    	zMauveWriter.__init__c             C   s   t  |  } | j   |  _ | d k r3 t d   |  j d k rN t d   |  j s d |  _ |  j j d  x5 t d | d  D]  } |  j j d | | f  q Wx- t |  D] \ } } |  j	 | d | q W|  j j d	  d
 S)zUse this to write (another) single alignment to an open file.

        Note that sequences and their annotation are recorded
        together (rather than having a block of annotation followed
        by a block of aligned sequences).
        r   zMust have at least one sequencez Non-empty sequences are requiredTz#FormatVersion Mauve1
r   z#Sequence%sEntry	%s

record_idxz=
N)
lenZget_alignment_length_length_of_sequences
ValueErrorr   handlewriterange	enumerate_write_record)r   	alignmentcountiidxrecordr   r   r   write_alignmentt   s    		zMauveWriter.write_alignmentr   c       	      C   s  |  j  t | j  k r$ t d   | j } y t t | j   } Wn" t k
 rj t | d  } Yn Xd | j k rId | j k rId t | j d  t | j d  f } d t | j d d  t | j d  f } | t |  d  | k r| d t |   } | t |  d  | k rI| d t |   } d | j k rd | j k rd | j k rt j	 d | d | j d d d | j d d | j d d k rd	 n d
 d | j d d | j
  } d } n@ t j	 d | d d d d d d	 d | j d d | j
  } d } d | k s<d | k r| r|  j sd |  _ t j	 d | d d d d d d	 d | j d d | j
  } |  j j | d  na |  j j |  xN t d t | j  d  D]1 } |  j j d t | j | | d    qWd S)z/Write a single SeqRecord to the file (PRIVATE).z%Sequences must all be the same lengthr   r   r   z/%s-%sNr   seq_name+r
   filez.faZ	ugly_hackFr   Tz:0-0 z:1-0 
P   z%s
)r!   r    seqr"   namestrr   annotationsID_LINE_FMTformatr   r   r#   r$   r%   )	r   r,   r   r.   Zsuffix0Zsuffix1Zid_lineZlacking_annotationsr*   r   r   r   r'      sf    							"zMauveWriter._write_record)__name__
__module____qualname____doc__r   r-   r'   r   r   )r   r   r   k   s   !r   c               @   s(   e  Z d  Z d Z g  Z d d   Z d S)MauveIteratorzMauve xmfa alignment iterator.c             C   sN  |  j  } | j   } | s! t  x+ | rN | j   j d  rN | j   } q$ Wi  } i  } d } d } x| sq P| j   } | j d  r Pn[| j d  rt j |  } | s t j |  } | s t d |   | j	 d  } i  }	 x d D]~ }
 yc | j	 |
  } |
 d k r:t
 |  } | d k r:| d 8} |
 d	 k rRt
 |  } | |	 |
 <Wq t k
 rqYq Xq W|	 | | <| |  j k r|  j j |  | j | d  | } n3 | st  | d k rt d   | | | 7<| j   } qj Wt |  t |  j  k st  |  j |  _ | |  _ |  j rD| rDt t t t | j      } g  } x|  j D]} | | k st | |  d k st | |  d k rd | } n
 | | } | t |  k rt d   | | k rqq| | d d k s| | d	 d k rd j | |   } d | | k rO| | d } n | | d } | j |  d k r| | 7} n/ d | | k r| | d } n | | d } t t | |  j  d | d | } | | d | j d <| | d	 | j d	 <| | d
 d k rd n d | j d
 <| j |  qqWt | |  j  St  d S)z)Parse the next alignment from the handle.#FN=>zMalformed header line: %sr   r   r   r   r4   realnamer   r    z#Saw sequence before definition liner
   z8Sequences have different lengths, or repeated identifierz/{start}-{end}r/   )zstartzendzidzstrandznamerA   )r#   readlineStopIterationstrip
startswithXMFA_HEADER_REGEX_BIOPYTHONmatchXMFA_HEADER_REGEXr"   groupr   
IndexError_idsappend
setdefaultAssertionErrorr    ids	sequencesmaxr   listvaluesr8   r)   r   r   Zalphabetr6   r   )r   r#   lineZseqsZseq_regionsZpassed_end_alignmentZ	latest_idmZ	parsed_idZparsed_datakeyvalueZalignment_lengthrecordsr   r3   suffixZcorrected_idr,   r   r   r   __next__   s    	
	
	!	!8
	($'zMauveIterator.__next__N)r9   r:   r;   r<   rM   r\   r   r   r   r   r=      s   r=   )r<   
__future__r   reZBio.Seqr   ZBio.SeqRecordr   Z	Bio.Alignr   Z
Interfacesr   r   compilerJ   rH   r7   r   r   r=   r   r   r   r   <module>N   s   		z