
:>"^I                 @   s  d  Z  d d l m Z m Z d d l m Z d d l m Z d d l m	 Z	 m
 Z
 m Z d d l m Z m Z m Z d d l m Z Gd d	   d	 e  Z e	 d
 d d  Z e	 d d  Z d d   Z d d   Z d d   Z d d   Z d d   Z e d k rd d l m Z e   d S)zCode for dealing with Codon Alignment.

CodonAlignment class is inherited from MultipleSeqAlignment class. This is
the core class to deal with codon alignment in biopython.
    )divisionprint_function)MultipleSeqAlignment)	SeqRecord)default_codon_tabledefault_codon_alphabetcompare_codon_alphabet)_get_codon_listCodonSeq	cal_dn_ds)	chisqprobc               @   s   e  Z d  Z d Z d d e d d  Z d d   Z d d d	  Z d
 d   Z d d   Z	 d d   Z
 d e d d  Z d d e d d  Z e e d d   Z d S)CodonAlignmenta  Codon Alignment class that inherits from MultipleSeqAlignment.

    >>> from Bio.Alphabet import generic_dna
    >>> from Bio.SeqRecord import SeqRecord
    >>> from Bio.Alphabet import IUPAC, Gapped
    >>> a = SeqRecord(CodonSeq("AAAACGTCG", alphabet=default_codon_alphabet), id="Alpha")
    >>> b = SeqRecord(CodonSeq("AAA---TCG", alphabet=default_codon_alphabet), id="Beta")
    >>> c = SeqRecord(CodonSeq("AAAAGGTGG", alphabet=default_codon_alphabet), id="Gamma")
    >>> print(CodonAlignment([a, b, c]))
    CodonAlphabet(Standard) CodonAlignment with 3 rows and 9 columns (3 codons)
    AAAACGTCG Alpha
    AAA---TCG Beta
    AAAAGGTGG Gamma

     Nc             C   sk   t  j |  | d | x, |  D]$ } t | j t  s t d   q W|  j   d d k rg t d   d S)zInitialize the class.alphabetzACodonSeq objects are expected in each SeqRecord in CodonAlignment   r   zKAlignment length is not a multiple of three (i.e. a whole number of codons)N)r   __init__
isinstanceseqr
   	TypeErrorget_alignment_length
ValueError)selfrecordsnamer   rec r   B/tmp/pip-build-ww9dw3qa/biopython/Bio/codonalign/codonalignment.pyr   (   s    zCodonAlignment.__init__c                s   t    j  } d t   j  |   j     j   f g } | d k ro | j   f d d     j D  n] | j   f d d     j d d  D  | j d  | j   j   j d d
 d  d j	 |  S)aD  Return a multi-line string summary of the alignment.

        This output is indicated to be readable, but large alignment
        is shown truncated. A maximum of 20 rows (sequences) and
        60 columns (20 codons) are shown, with the record identifiers.
        This should fit nicely on a single screen. e.g.

        z9%s CodonAlignment with %i rows and %i columns (%i codons)<   c                s%   g  |  ] }   j  | d  d  q S)lengthr   )	_str_line).0r   )r   r   r   
<listcomp>E   s   	z*CodonAlignment.__str__.<locals>.<listcomp>c                s%   g  |  ] }   j  | d  d  q S)r   r   )r   )r    r   )r   r   r   r!   H   s   	N   z...   r   
)
len_recordsstr	_alphabetr   get_aln_lengthextendappendr   join)r   Zrowslinesr   )r   r   __str__6   s    	#zCodonAlignment.__str__c                s,  t  | t  r |  j | St  | t  r@ t |  j | |  j  St |  d k r^ t d   | \ }   t  | t  r |  j |   St    t  r d j   f d d   |  j | D  Sd d l	 m
 } | d k rt   f d	 d   |  j | D |  St   f d
 d   |  j | D |  Sd S)z3Return a CodonAlignment object for single indexing.   zInvalid index type.r   c             3   s   |  ] } t  |    Vq d  S)N)r(   )r    r   )	col_indexr   r   	<genexpr>[   s    z-CodonAlignment.__getitem__.<locals>.<genexpr>r   )generic_nucleotideNc             3   s   |  ] } |   Vq d  S)Nr   )r    r   )r1   r   r   r2   `   s    c             3   s   |  ] } |   Vq d  S)Nr   )r    r   )r1   r   r   r2   d   s    )r   intr'   slicer   r)   r&   r   r-   ZBio.Alphabetr3   r   )r   indexr   Z	row_indexr3   r   )r1   r   __getitem__N   s(    zCodonAlignment.__getitem__c             C   s   t  | t  r t |   t |  k r3 t d   t |  j | j  r} |  j } d d   t |  |  D } t | d | St d   n\ t  | t  r t |   t |  k r t d   |  j	   | St d j
 t |     d S)ah  Combine two codonalignments with the same number of rows by adding them.

        The method also allows to combine a CodonAlignment object with a
        MultipleSeqAlignment object. The following rules apply:

            * CodonAlignment + CodonAlignment -> CodonAlignment
            * CodonAlignment + MultipleSeqAlignment -> MultipleSeqAlignment
        zTWhen adding two alignments they must have the same length (i.e. same number or rows)c             s   sL   |  ]B \ } } t  d  t t | j  t | j  d | j j  Vq d S)r   r   N)r   r
   r(   r   r   )r    leftrightr   r   r   r2   x   s    z)CodonAlignment.__add__.<locals>.<genexpr>r   z@Only CodonAlignment with the same CodonAlphabet can be combined.zjOnly CodonAlignment or MultipleSeqAlignment object can be added with a CodonAlignment object. {} detected.N)r   r   r&   r   r   r)   zipr   r   toMultipleSeqAlignmentformatobject)r   otheralphaZmergedr   r   r   __add__h   s    			zCodonAlignment.__add__c             C   s   |  j    d S)zGet aligment length.r   )r   )r   r   r   r   r*      s    zCodonAlignment.get_aln_lengthc             C   s    d d   |  j  D } t |  S)zConvert the CodonAlignment to a MultipleSeqAlignment.

        Return a MultipleSeqAlignment containing all the
        SeqRecord in the CodonAlignment using Seq to store
        sequences
        c             S   s.   g  |  ]$ } t  | j j   d  | j  q S)id)r   r   ZtoSeqrA   )r    r   r   r   r   r!      s   	z9CodonAlignment.toMultipleSeqAlignment.<locals>.<listcomp>)r'   r   )r   Z
alignmentsr   r   r   r;      s    	z%CodonAlignment.toMultipleSeqAlignmentZNG86c          	   C   s=  d d l  m } d d   |  j D } t |  j  } g  } g  } x t |  D] } | j g   | j g   x t | d  D] }	 | |	 k r t |  j | |  j |	 d | d | \ }
 } | | j |
  | | j |  q | | j d  | | j d  q WqN W| | d	 | } | | d	 | } | | f S)
zAvailable methods include NG86, LWL85, YN00 and ML.

        Argument:
         - method       - Available methods include NG86, LWL85, YN00 and ML.
         - codon_table  - Codon table to use for forward translation.

        r   )DistanceMatrixc             S   s   g  |  ] } | j   q Sr   )rA   )r    ir   r   r   r!      s   	 z3CodonAlignment.get_dn_ds_matrix.<locals>.<listcomp>r#   methodcodon_tableg        Zmatrix)Bio.Phylo.TreeConstructionrB   r'   r&   ranger,   r   )r   rD   rE   ZDMnamessizeZ	dn_matrixZ	ds_matrixrC   jdnZdsdn_dmds_dmr   r   r   get_dn_ds_matrix   s&    zCodonAlignment.get_dn_ds_matrixUPGMAc             C   s   d d l  m } |  j d | d |  \ } } |   } |   } | d k rm | j |  }	 | j |  }
 nB | d k r | j |  }	 | j |  }
 n t d j |    |	 |
 f S)zCnstruct dn tree and ds tree.

        Argument:
         - dn_ds_method - Available methods include NG86, LWL85, YN00 and ML.
         - tree_method  - Available methods include UPGMA and NJ.

        r   )DistanceTreeConstructorrD   rE   rO   ZNJz:Unknown tree method ({0}). Only NJ and UPGMA are accepted.)rF   rP   rN   ZupgmaZnjRuntimeErrorr<   )r   Zdn_ds_methodZtree_methodrE   rP   rL   rM   Zdn_constructorZds_constructorZdn_treeZds_treer   r   r   get_dn_ds_tree   s    			zCodonAlignment.get_dn_ds_treec                s,     f d d   | j  D } |  | d   S)zConvert a MultipleSeqAlignment to CodonAlignment.

        Function to convert a MultipleSeqAlignment to CodonAlignment.
        It is the user's responsibility to ensure all the requirement
        needed by CodonAlignment is met.
        c                s:   g  |  ]0 } t  t t | j  d    d | j  q S)r   rA   )r   r
   r(   r   rA   )r    rC   )r   r   r   r!      s   	z+CodonAlignment.from_msa.<locals>.<listcomp>r   )r'   )clsZalignr   r   r   )r   r   from_msa   s    zCodonAlignment.from_msa)__name__
__module____qualname____doc__r   r   r/   r7   r@   r*   r;   r   rN   rR   classmethodrT   r   r   r   r   r      s   r   g?c                s  d d l  } t d d   |  D  s1 t d   d d   |  D } t t |   d k rh t d	   | d d
 } | j | j  } x | j D] } d | | <q Wg  } xF |  D]> }	 | j	 g   x( |	 D]    | d j	 t
   j   q Wq Wg  }
 x^ t |  D]P   g  } x4 | D], }   f d d   | D } | j	 |  qW|
 j	 |  qWd \ } } } } t d |  \ } } x|
 D]    d j   d d    } d | k st |  d k rqt d d     D  } | rDt | |  } t | |  } t | |  } t | |  | } | | 7} | | 7} qt | |  } t | |  } t | |  } t | |  | } | | 7} | | 7} qWt | | | | g  S)a  McDonald-Kreitman test for neutrality.

    Implement the McDonald-Kreitman test for neutrality (PMID: 1904993)
    This method counts changes rather than sites
    (http://mkt.uab.es/mkt/help_mkt.asp).

    Arguments:
     - codon_alns  - list of CodonAlignment to compare (each
       CodonAlignment object corresponds to gene sampled from a species)

    Return the p-value of test result.
    r   Nc             s   s   |  ] } t  | t  Vq d  S)N)r   r   )r    rC   r   r   r   r2      s    zmktest.<locals>.<genexpr>z#mktest accepts CodonAlignment list.c             S   s   g  |  ] } | j     q Sr   )r   )r    rC   r   r   r   r!      s   	 zmktest.<locals>.<listcomp>r#   z;CodonAlignment object for mktest should be of equal length.r   stopc                s   h  |  ] } |    q Sr   r   )r    k)rC   r   r   	<setcomp>   s   	 zmktest.<locals>.<setcomp>rE   -c             s   s!   |  ] } t  |  d  k Vq d S)r#   N)r&   )r    r[   r   r   r   r2     s    r%   )r   r   r   r   )copyallr   r&   setrQ   deepcopyforward_tablestop_codonsr,   r	   r   rG   _get_codon2codon_matrixunion_get_subgraph_count_replacement_G_test)Z
codon_alnsrE   r?   r^   Zcodon_aln_lenZ	codon_num
codon_dictrZ   Z	codon_lstZ	codon_aln	codon_setZuniq_codonsrJ   Z
uniq_codonZsyn_fixZ
nonsyn_fixZsyn_polyZnonsyn_polyGnonsyn_GZ	all_codonZ
fix_or_notZnonsyn_subgraphsubgraphZthis_nonZthis_synr   )rC   r   mktest   sV    "

rn   c             C   s  d } d d   t  |  j j    |  j D } |  j } x |  j D] } d | | <qB Wt |  } i  } i  } i  } i  }	 x t |  D] \ }
 } i  | | <i  |	 | <x t |  D] \ } } x | D] } | d |  | | | d	 d
  } | | | | k r&d	 |	 | | <d	 | | | <q | | k r d |	 | | <d	 | | | <q Wq Wq Wx | D] } i  | | <i  | | <xm | D]e } | | k rd | | | <d | | | <qt |	 | |  | | | <t | | |  | | | <qWqaW| | f S)zGet codon codon substitution matrix (PRIVATE).

    Elements in the matrix are number of synonymous and nonsynonymous
    substitutions required for the substitution.
    ATCrk   c             S   s"   g  |  ] } d  | k r |  q S)Ur   )r    rC   r   r   r   r!     s   	 z+_get_codon2codon_matrix.<locals>.<listcomp>rZ   r   r#   Ng?)ro   rp   rq   rk   )listrb   keysrc   r&   	enumerate	_dijkstra)rE   Z
base_tuplecodonsri   rZ   numrk   rl   graphZgraph_nonsynrC   ZcodonpbrJ   Z	tmp_codonZcodon1Zcodon2r   r   r   rd     sD    	

&

	"rd   c             C   s  i  } i  } x( |  j    D] } d | | <d | | <q Wd | | <t |  j     } x t |  d k r6d } d } xM | D]E } | d k r | | } | } q{ | | | k  r{ | | } | } q{ W| j |  xR |  | j   D]@ \ }	 }
 | |	 | | |
 k r | | |
 | |	 <| | |	 <q W| | k rV PqV Wg  } | } d } xC | | k s| j |  d k r| j d |  | | } qLPqLW| j d |  x< t t |  d  D]$ } | |  | | | | d 7} qW| S)a  Dijkstra's algorithm Python implementation (PRIVATE).

    Algorithm adapted from
    http://thomas.pelletier.im/2010/02/dijkstras-algorithm-python-implementation/.
    However, an obvious bug in::

        if D[child_node] >(<) D[node] + child_value:

    is fixed.
    This function will return the distance between start and end.

    Arguments:
     - graph: Dictionary of dictionary (keys are vertices).
     - start: Start vertex.
     - end: End vertex.

    Output:
       List of vertices from the beginning to the end.

    d   r   r   Nr#   )rt   rs   r&   removeitemscountinsertrG   )ry   startendDPnodeZunseen_nodesZshortestZ	temp_nodeZ
child_nodeZchild_valuepathZdistancerC   r   r   r   rv   E  sH    


	

"rv   c             C   sx   d d l  m } t |   d k r& d St |   d k r^ t |   } | | | d | d  St |   } t |  Sd S)z9Count replacement needed for a given codon_set (PRIVATE).r   )floorr#   r0   N)r   r   )mathr   r&   rs   _prim)rj   rk   r   rw   r   r   r   rg     s    rg   c             C   s  d d l  m } d d l m } d d l m } m } m } g  } g  } x |  j   D] } | j	 |  xj |  | D]^ }	 | |	 |  | |	 f | k rs |	 | |  | |	 f | k rs | j	 | |	 |  | |	 f  qs WqU W| t
  }
 xK | D]C \ } } } |
 | j	 | | | f  |
 | j	 | | | f  q Wg  } t | d  } |
 | d d d  } | |  x | r| |  \ } } } | | k rn| j |  | j	 | | | f  x/ |
 | D]# } | d | k r| | |  qWqnWd } x" | D] } | | | d  7} qW| S)zPrim's algorithm to find minimum spanning tree (PRIVATE).

    Code is adapted from
    http://programmingpraxis.com/2010/04/09/minimum-spanning-tree-prims-algorithm/
    r   )r   )defaultdict)heapifyheappopheappushNr0   )r   r   collectionsr   heapqr   r   r   rt   r,   rs   r`   add)rk   r   r   r   r   r   ZnodesedgesrC   rJ   connZn1Zn2cZmstusedZusable_edgesZcoster   rz   r   r   r   r     s<    :&
	r   c             C   sX   i  } xK |  D]C } i  | | <x0 |  D]( } | | k r$ | | | | | | <q$ Wq W| S)z<Get the subgraph that contains all codons in list (PRIVATE).r   )rw   rk   rm   rC   rJ   r   r   r   rf     s    
rf   c             C   s   d d l  m } d } t |   } |  d |  d } |  d |  d } t |  d d   } t |  d d   } | | | | | | | | | | | | g } x5 t |  |  D]$ \ }	 }
 | |	 | |	 |
  7} q W| d 9} t | d  S)zG test for 2x2 contingency table (PRIVATE).

    Arguments:
     - site_counts - [syn_fix, nonsyn_fix, syn_poly, nonsyn_poly]

    >>> print("%0.6f" % _G_test([17, 7, 42, 2]))
    0.004924
    r   )logr0   r#   r   N)r   r   sumr:   r   )Zsite_countsr   rk   ZtotZtot_synZtot_nonZtot_fixZtot_polyexpZobsexr   r   r   rh     s    
rh   __main__)run_doctestN)rX   
__future__r   r   Z	Bio.Alignr   ZBio.SeqRecordr   ZBio.codonalign.codonalphabetr   r   r   ZBio.codonalign.codonseqr	   r
   r   ZBio.codonalign.chisqr   r   rn   rd   rv   rg   r   rf   rh   rU   Z
Bio._utilsr   r   r   r   r   <module>
   s"   @.D&