
:>"^@Q                 @   s   d  Z  d d l Z d d l Z y d d l Z Wn. e k
 r^ d d l m Z e d   Yn Xd d l m	 Z	 d d l
 m Z d d l m Z d	 d
   Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z d S)zSupport for various forms of sequence motif matrices.

Implementation of frequency (count) matrices, position-weight matrices,
and position-specific scoring matrices.
    N)MissingPythonDependencyErrorz3Install NumPy if you want to use Bio.motifs.matrix.)range)Seq   )_pwmc                sk   t  |  } t j | | d t j  } t j   f d d   t |  D t  } t j | | |  | S)z(Calculate scores using C code (PRIVATE).r   c                s,   g  |  ]"      f d  d   d D  q S)c                s   g  |  ] }  |    q S r   ).0letter)i
score_dictr   6/tmp/pip-build-ww9dw3qa/biopython/Bio/motifs/matrix.py
<listcomp>    s   	 z)_calculate.<locals>.<listcomp>.<listcomp>ACGTr   )r   )r   )r
   r   r       s   	z_calculate.<locals>.<listcomp>)	lennpemptyZfloat32arrayr   floatr   	calculate)r   sequencemnscoreslogoddsr   )r   r   
_calculate   s    r   c               @   s   e  Z d  Z d Z d d   Z d d   Z d d   Z e d d	    Z e d
 d    Z	 e d d    Z
 e d d    Z d d   Z d S)GenericPositionMatrixz9Base class for the support of position matrix operations.c             C   s   d |  _  xl | D]d } |  j  d k r; t | |  |  _  n% |  j  t | |  k r` t d   t | |  |  | <q W| |  _ d S)zInitialize the class.Nzdata has inconsistent lengths)lengthr   	Exceptionlistalphabet)selfr   valuesr	   r   r   r   __init__)   s    	zGenericPositionMatrix.__init__c             C   s   d d   t  |  j  D } d d j |  } | g } xL |  j D]A } d d   |  | D } d | d j |  } | j |  qB Wd j |  d } | S)zPReturn a string containing nucleotides and counts of the alphabet in the Matrix.c             S   s   g  |  ] } d  |  q S)z%6dr   )r   r
   r   r   r   r   6   s   	 z1GenericPositionMatrix.__str__.<locals>.<listcomp>z    c             S   s   g  |  ] } d  |  q S)z%6.2fr   )r   valuer   r   r   r   :   s   	 z%c: 
)r   r   joinr   append)r    wordslinelinesr	   textr   r   r   __str__4   s    	zGenericPositionMatrix.__str__c                s  t  | t  rt |  d k r| \ } } t  | t  r | j t   j   \ } } } t | | |  }   f d d   | D } d }	 n t  | t  r   j | }
 d }	 n t  | t  r   f d d   | D } d }	 nT t  | t  r&t |  d k r| }
 d }	 q;t	 |   n t	 d t |    t  | t  r| j   j
  \ } } } t | | |  } d } n3 t  | t  r| } d } n t	 d t |    |	 d k r| d k rt j   |
  | S|	 d k r&| d k r&t j   |
   t  f d d   | D  S|	 d k rs| d k rsi  } x( | D]  }
 t j   |
  | | |
 <qKW| Si  } x= | D]5 }
 t j   |
    f d	 d   | D | |
 <qWt |    j k r  j   j |  S| Sn+ t |  d k r| d
 } n t	 d   t  | t  rw| j t   j   \ } } } t | | |  }   f d d   | D } d } n t  | t  r  j | } d } n t  | t  r  f d d   | D } d } nT t  | t  rt |  d k r| } d } q!t	 |   n t	 d t |    | d k r=t j   |  S| d k rzi  } x$ | D] } t j   |  | | <qVW| St d   d S)z(Return the position matrix of index key.   c                s   g  |  ] }   j  |  q Sr   )r   )r   r
   )r    r   r   r   H   s   	 z5GenericPositionMatrix.__getitem__.<locals>.<listcomp>r   c                s   g  |  ] }   j  |  q Sr   )r   )r   r
   )r    r   r   r   N   s   	 zCannot understand key %sc             3   s   |  ] }   | Vq d  S)Nr   )r   index2)r!   r   r   	<genexpr>e   s    z4GenericPositionMatrix.__getitem__.<locals>.<genexpr>c                s   g  |  ] }   |  q Sr   r   )r   _)r!   r   r   r   o   s   	 r   z"keys should be 1- or 2-dimensionalc                s   g  |  ] }   j  |  q Sr   )r   )r   r
   )r    r   r   r   {   s   	 c                s   g  |  ] }   j  |  q Sr   )r   )r   r
   )r    r   r   r      s   	 zShould not get hereN)
isinstancetupler   sliceindicesr   r   intstrKeyErrorr   dict__getitem__sorted	__class__RuntimeError)r    keykey1key2Zstart1Zstop1Zstride1Zindices1Zletters1Zdim1Zletter1Zstart2Zstop2Zstride2Zindices2Zdim2r.   dstartstopZstrider4   lettersZdimr	   r   )r    r!   r   r9   @   s    !						!!				z!GenericPositionMatrix.__getitem__c             C   s   d } x t  |  j  D]u } y t d  } Wn t k
 rF d } Yn Xx7 |  j D], } |  | | } | | k rQ | } | } qQ W| | 7} q Wt |  S)zReturn the consensus sequence. z-infg      g      )r   r   r   
ValueErrorr   r   )r    r   r
   maximumr	   countsequence_letterr   r   r   	consensus   s    
zGenericPositionMatrix.consensusc             C   s   d } x t  |  j  D]u } y t d  } Wn t k
 rF d } Yn Xx7 |  j D], } |  | | } | | k  rQ | } | } qQ W| | 7} q Wt |  S)z"Return the anticonsensus sequence.rD   infg      )r   r   r   rE   r   r   )r    r   r
   Zminimumr	   rG   rH   r   r   r   anticonsensus   s    
z#GenericPositionMatrix.anticonsensusc                s  d d d d d d d d d d d d d	 d
 d d d d d d d d d d d d d d d d i } d } xEt   j  D]4     f d d   } t  d | d d  }    f d! d"   | D } | d# t | d$ d%   k r
| d# d& | d$ k r
| d# } n d' t | d% d&   d( t |  k rVd j t | d% d&    } n8 | d( d# k rd j t | d% d(    } n d } | j | |  } | | 7} qv Wt |  S))z)Return the degenerate consensus sequence.ACGTZACMZAGRATWCGSZCTYGTKZACGVZACTHZAGTDZCGTBr   NrD   c                s    |    S)Nr   )
nucleotide)r
   r    r   r   get   s    z7GenericPositionMatrix.degenerate_consensus.<locals>.getr=   reverseTc                s   g  |  ] }  |    q Sr   r   )r   c)r
   r    r   r   r      s   	 z>GenericPositionMatrix.degenerate_consensus.<locals>.<listcomp>r   r   Nr-         )r   r   r:   sumr&   r_   r   )r    Zdegenerate_nucleotider   r_   Znucleotidescountsr=   r^   r   )r
   r    r   degenerate_consensus   s<    	8*""z*GenericPositionMatrix.degenerate_consensusc             C   sx   |  j  } d } d } xX t |  j  D]G } x> | D]6 } | d k rV | |  | | 7} | |  | | 7} q2 Wq% W| | S)z Compute the fraction GC content.g        rT   )r   r   r   )r    r   Zgc_totaltotalr
   r	   r   r   r   
gc_content   s    	z GenericPositionMatrix.gc_contentc             C   s   i  } |  j  d k rN |  d d d d	  | d <|  d d d d
  | d <n6 |  d d d d  | d <|  d d d d  | d <|  d d d d  | d <|  d d d d  | d <|  j  } |  j | |  S)zCompute reverse complement.ZACGUUNr   rL   rO   rM   rN   rj   rj   rj   rj   rj   )r   r;   )r    r!   r   r   r   r   reverse_complement   s    	z(GenericPositionMatrix.reverse_complementN)__name__
__module____qualname____doc__r"   r,   r9   propertyrI   rK   rf   rh   rk   r   r   r   r   r   &   s   U,r   c               @   s%   e  Z d  Z d Z d d d  Z d S)FrequencyPositionMatrixzGClass for the support of frequency calculations on the Position Matrix.Nc             C   s  i  } | d k r= x |  j  D] } d g |  j | | <q Wnr t | t  r x` |  j  D]$ } t | |  g |  j | | <qV Wn. x+ |  j  D]  } t |  g |  j | | <q WxE t |  j  D]4 } x+ |  j  D]  } | | | |  | | 7<q Wq Wt |  j  |  S)a  Create and return a position-weight matrix by normalizing the counts matrix.

        If pseudocounts is None (default), no pseudocounts are added
        to the counts.

        If pseudocounts is a number, it is added to the counts before
        calculating the position-weight matrix.

        Alternatively, the pseudocounts can be a dictionary with a key
        for each letter in the alphabet associated with the motif.
        Ng        )r   r   r1   r8   r   r   PositionWeightMatrix)r    Zpseudocountsre   r	   r
   r   r   r   	normalize  s    %"z!FrequencyPositionMatrix.normalize)rl   rm   rn   ro   rs   r   r   r   r   rq     s   rq   c               @   s1   e  Z d  Z d Z d d   Z d d d  Z d S)rr   zDClass for the support of weight calculations on the Position Matrix.c                s   t  j  | |  x\ t  j  D]K   t    f d d   | D  } x  | D] }  |   | <qR Wq# Wx" | D] } t  |   | <qy Wd S)zInitialize the class.c             3   s#   |  ] } t   |    Vq d  S)N)r   )r   r	   )r
   r    r   r   r/   *  s    z0PositionWeightMatrix.__init__.<locals>.<genexpr>N)r   r"   r   r   rd   r2   )r    r   re   rg   r	   r   )r
   r    r   r"   &  s    "zPositionWeightMatrix.__init__Nc             C   su  i  } |  j  } | d k r3 t j |  j  d  } n t |  } t | j    } x& | D] } | | | <g  | | <qX Wx t |  j  D] } x | D] } | | } | d k r|  | | } | d k r t j | | d  }	 qIy t	 d  }	 WqIt
 k
 rd	 }	 YqIXn5 |  | | } | d k r=t	 d  }	 n t	 d  }	 | | j |	  q Wq Wt | |  }
 |
 S)
a/  Return the Position-Specific Scoring Matrix.

        The Position-Specific Scoring Matrix (PSSM) contains the log-odds
        scores computed from the probability matrix and the background
        probabilities. If the background is None, a uniform background
        distribution is assumed.
        Ng      ?r   r-   z-infg      rJ   nang      )r   r8   fromkeysrd   r!   r   r   mathlogr   rE   r'   PositionSpecificScoringMatrix)r    
backgroundr!   r   rg   r	   r
   bpr   pssmr   r   r   log_odds0  s6    	
zPositionWeightMatrix.log_odds)rl   rm   rn   ro   r"   r}   r   r   r   r   rr   #  s   
rr   c               @   s   e  Z d  Z d Z d d   Z d d d d d	  Z e d
 d    Z e d d    Z e d d    Z	 d d d  Z
 d d d  Z d d   Z d d   Z d d d d  Z d S)rx   zGClass for the support of Position Specific Scoring Matrix calculations.c             C   s}   t  |  j  d d d d g k r4 t d |  j   t |  } |  j } t |  | |  } t |  d k ru | d S| Sd S)	ao  Return the PWM score for a given sequence for all positions.

        Notes:
         - the sequence can only be a DNA sequence
         - the search is performed only on one strand
         - if the sequence and the motif have the same length, a single
           number is returned
         - otherwise, the result is a one-dimensional list or numpy array

        rL   rM   rN   rO   z6PSSM has wrong alphabet: %s - Use only with DNA motifsr   r   N)r:   r   rE   r6   r   r   r   )r    r   r   r   r   r   r   r   _  s    !	z'PositionSpecificScoringMatrix.calculateg        T
      c             c   s  | j    } t |  } |  j } t j d | |  } | rH |  j   } xW| D]O}	 | |	 |	 | | d  }
 |  j |
  } | | k } t j |  d |	 } | | } | r | j |
  } | | k } t j |  d |	 } | | } n* t j d d t	 } t j d d t	 } t j
 | | |  } t j
 | |  } t j t j
 | |   } | | } | | } x( t | |  D] \ } } | | f VqWqO Wd S)zFind hits with PWM score above given threshold.

        A generator function, returning found hits in the given sequence
        with the pwm score higher than the threshold.
        r   r   ZdtypeN)upperr   r   r   Zarangerk   r   wherer   r5   r'   Zargsortzip)r    r   	thresholdZboth	chunksizeZseq_lenZmotif_lZchunk_startsrcZchunk_startZsubseqZ
pos_scoresZpos_indZpos_positionsZ
neg_scoresZneg_indZneg_positionsZchunk_positionsZchunk_scoresorderposscorer   r   r   search{  s4    	


z$PositionSpecificScoringMatrix.searchc                sV   d }  j  } x@ t d  j  D],   | t    f d d   | D  7} q" W| S)zoMaximal possible score for this motif.

        returns the score computed for the consensus sequence.
        g        r   c             3   s   |  ] }  |   Vq d  S)Nr   )r   r	   )positionr    r   r   r/     s    z4PositionSpecificScoringMatrix.max.<locals>.<genexpr>)r   r   r   max)r    r   rC   r   )r   r    r   r     s
    	*z!PositionSpecificScoringMatrix.maxc                sV   d }  j  } x@ t d  j  D],   | t    f d d   | D  7} q" W| S)zsMinimal possible score for this motif.

        returns the score computed for the anticonsensus sequence.
        g        r   c             3   s   |  ] }  |   Vq d  S)Nr   )r   r	   )r   r    r   r   r/     s    z4PositionSpecificScoringMatrix.min.<locals>.<genexpr>)r   r   r   min)r    r   rC   r   )r   r    r   r     s
    	*z!PositionSpecificScoringMatrix.minc             C   s   t  d   d S)zCompute the GC-ratio.z,Cannot compute the %GC composition of a PSSMN)r   )r    r   r   r   rh     s    z(PositionSpecificScoringMatrix.gc_contentNc       	      C   s
  | d k r$ t  j |  j d  } n t  |  } t | j    } x |  j D] } | | | <qL Wd } x t |  j  D] } x |  j D]t } |  | | f } t j |  r q t j	 |  r | d k  r q | | } | t j
 d |  } | | | 7} q Wqz W| S)z.Return expected value of the score of a motif.Ng      ?g        r   r-   )r8   ru   r   rd   r!   r   r   rv   isnanisinfpow)	r    ry   rg   r	   sxr
   r   rz   r{   r   r   r   mean  s$    
z"PositionSpecificScoringMatrix.meanc             C   sX  | d k r$ t  j |  j d  } n t  |  } t | j    } x |  j D] } | | | <qL Wd } x t |  j  D] } d } d } x |  j D] } |  | | f } t j |  r q t j	 |  r | d k  r q | | }	 |	 t j
 d |  }
 | |
 | 7} | |
 | | 7} q W| | | 8} | | 7} qz Wt | d  } t j |  S)z2Return standard deviation of the score of a motif.Ng      ?g        r   r-   )r8   ru   r   rd   r!   r   r   rv   r   r   r   r   sqrt)r    ry   rg   r	   Zvariancer
   r   sxxr   rz   r{   r   r   r   std  s0    
z!PositionSpecificScoringMatrix.stdc             C   s   |  j  | j  k r t d   d } xo t |  j d | j  D]S } | d k  rg |  j | |  } n | j |  |  } | | k  r? | } | } q? Wd | | f S)zReturn the similarity score based on pearson correlation for the given motif against self.

        We use the Pearson's correlation of the respective probabilities.
        z.Cannot compare motifs with different alphabetsr-   r   r   )r   rE   r   r   dist_pearson_at)r    otherZmax_poffsetr{   Zmax_or   r   r   dist_pearson  s    !z*PositionSpecificScoringMatrix.dist_pearsonc                s   j  } d } d } d } d } d } t  j    j  t |  }	 x t t  j    j   D]      f d d   | D }
   f d d   | D } | t |
  7} | t |  7} | t d d   |
 D  7} | t d d   t |
 |  D  7} | t d d   | D  7} qj W| |	 } | |	 } | |	 } | |	 } | |	 } | | | } t j	 | | | | | |  } | | S)	zMReturn the similarity score based on pearson correlation at the given offset.g        c                s$   g  |  ] }  |    f  q Sr   r   )r   r	   )r   r   r    r   r   r   	  s   	 zAPositionSpecificScoringMatrix.dist_pearson_at.<locals>.<listcomp>c                s    g  |  ] }   |  f  q Sr   r   )r   r	   )r   r   r   r   r   
  s   	 c             s   s   |  ] } | | Vq d  S)Nr   )r   xr   r   r   r/     s    z@PositionSpecificScoringMatrix.dist_pearson_at.<locals>.<genexpr>c             s   s   |  ] \ } } | | Vq d  S)Nr   )r   r   yr   r   r   r/     s    c             s   s   |  ] } | | Vq d  S)Nr   )r   r   r   r   r   r/     s    )
r   r   r   r   r   r   rd   r   rv   r   )r    r   r   rC   r   Zsyr   ZsxyZsyyZnormxiyi	numeratordenominatorr   )r   r   r   r    r   r     s.    	#&&!




#z-PositionSpecificScoringMatrix.dist_pearson_atrc   c             C   s   d d l  m } | d k r4 t j |  j d  } n t |  } t | j    } x |  j D] } | | | <q\ W| d | d |  d |  S)z@Calculate the distribution of the scores at the given precision.r   )ScoreDistributionNg      ?	precisionr|   ry   )Z
thresholdsr   r8   ru   r   rd   r!   )r    ry   r   r   rg   r	   r   r   r   distribution  s    z*PositionSpecificScoringMatrix.distributioni@B i  )rl   rm   rn   ro   r   r   rp   r   r   rh   r   r   r   r   r   r   r   r   r   rx   \  s   "rx   )ro   rv   platformZnumpyr   ImportErrorZBior   Z	Bio._py3kr   ZBio.Seqr   rD   r   r   r8   r   rq   rr   rx   r   r   r   r   <module>	   s     9