
    {Ti>                         d 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
  G d de      Zd	 ZddZd ZddZd Zd Zd Zd Zd Zd Zd dZd Zd Zd Zd Zd Zd Zd Zedk(  rddlm Z   e         y
y
)!zCode for dealing with coding sequence.

CodonSeq class is inherited from Seq class. This is the core class to
deal with sequences in CodonAlignment in biopython.

    )permutationslog)
CodonTable)Seq)	SeqRecordc                   \    e Zd ZdZddZd Zd Z	 ddZd Zd Z	dd	Z
dd
Zedd       Zy)CodonSeqaK  CodonSeq is designed to be within the SeqRecords of a CodonAlignment class.

    CodonSeq is useful as it allows the user to specify
    reading frame when translate CodonSeq

    CodonSeq also accepts codon style slice by calling
    get_codon() method.

    **Important:** Ungapped CodonSeq can be any length if you
    specify the rf_table. Gapped CodonSeq should be a
    multiple of three.

    >>> codonseq = CodonSeq("AAATTTGGGCCAAATTT", rf_table=(0,3,6,8,11,14))
    >>> print(codonseq.translate())
    KFGAKF

    test get_full_rf_table method

    >>> p = CodonSeq('AAATTTCCCGG-TGGGTTTAA', rf_table=(0, 3, 6, 9, 11, 14, 17))
    >>> full_rf_table = p.get_full_rf_table()
    >>> print(full_rf_table)
    [0, 3, 6, 9, 12, 15, 18]
    >>> print(p.translate(rf_table=full_rf_table, ungap_seq=False))
    KFPPWV*
    >>> p = CodonSeq('AAATTTCCCGGGAA-TTTTAA', rf_table=(0, 3, 6, 9, 14, 17))
    >>> print(p.get_full_rf_table())
    [0, 3, 6, 9, 12.0, 15, 18]
    >>> p = CodonSeq('AAA------------TAA', rf_table=(0, 3))
    >>> print(p.get_full_rf_table())
    [0, 3.0, 6.0, 9.0, 12.0, 15]

    Nc           	         t        j                  | |j                                || _        |Lt	        |       }|dz  dk7  rt        d      t        t        d|| j                  |      z
  d            | _	        yt        |t        t        f      st        d      t        d |D              st        d      || _	        y)zInitialize the class.N   r   zJSequence length is not a multiple of three (i.e. a whole number of codons)z)rf_table should be a tuple or list objectc              3   <   K   | ]  }t        |t                y wN)
isinstanceint).0is     J/home/agent/.local/lib/python3.12/site-packages/Bio/codonalign/codonseq.py	<genexpr>z$CodonSeq.__init__.<locals>.<genexpr>X   s     <az!S)<s   zSElements in rf_table should be int that specify the codon positions of the sequence)r   __init__uppergap_charlen
ValueErrorlistrangecountrf_tabler   tuple	TypeErrorall)selfdatar   r   lengths        r   r   zCodonSeq.__init__8   s     	T4::<(  YFzQ <  !q&4::h3G*G!KLDM
 h6 KLL<8<<# 
 %DM    c                 R    t         j                  D ch c]  }|dz  	 c}      dk7  rt        d      t        |t              r-|dk7  rt         |dz  |dz   dz         S t         |dz  d       S t        t               dz         fd} ||      }t        |      S c c}w )z&Get the index codon from the sequence.r      z}frameshift detected. CodonSeq object is not able to deal with codon sequence with frameshift. Please use normal slice option.Nc                 X    |    }d}|D ]  }||dz  |dz  dz    z  } t        |      S )N r   str)paa_slicecodon_slicer   aa_indexr!   s       r   cslicez"CodonSeq.get_codon.<locals>.csliceu   sH    #A; ! ;A4AA	#::K;;''r$   )r   r   RuntimeErrorr   r   r+   r   r
   )r!   indexr   r0   r.   r/   s   `    @r   	get_codonzCodonSeq.get_codon`   s    t}}-!A-.!3R  eS!{4	UQY!O<==4	,-- SY!^,H( !-KK((7 .s   B$c                 ,    t        | j                        S )z,Return the number of codons in the CodonSeq.)r   r   r!   s    r   get_codon_numzCodonSeq.get_codon_num   s    4==!!r$   c                    |t         j                  d   }g }|r&t        |       j                  | j                  d      }nt        |       }|| j
                  }d}|D ]  }t        |t              r|j                  d       %d|||dz    v r>|dk(  s||z
  dk(  r|}|||dz    j                  dd      dd }	n||z
  dkD  r|||dz    }	|}n
|||dz    }	|}	|j                  v r|j                  |       	 |j                  |j                  |	           dj                  |      S # t        $ r t        d|	 d	      w xY w)
a1  Translate the CodonSeq based on the reading frame in rf_table.

        It is possible for the user to specify
        a rf_table at this point. If you want to include
        gaps in the translated sequence, this is the only
        way. ungap_seq should be set to true for this
        purpose.
        Nr&   r)   r'   -r      zUnknown codon detected (z4). Did you forget to specify the ungap_seq argument?)r   generic_by_idr+   replacer   r   r   floatappendstop_codonsforward_tableKeyErrorr1   join)
r!   codon_tablestop_symbolr   	ungap_seqamino_acidstr_seqr,   r   codons
             r   	translatezCodonSeq.translate   s    $2215KY&&t}}b9FYF}}H 	A!U#""3' q1q5))7a!eqjA"1q1u-55c2>rBEUQY"1q1u-EA q1q5)///"";/"";#<#<U#CD/	: ww{##  ".ug 6A A s   5D&&D?c                 *    t        t        |             S )zConvert DNA to seq object.)r   r+   r5   s    r   toSeqzCodonSeq.toSeq   s    3t9~r$   c                    t        |       j                  dd      }| j                  d   g}t        dt	        | j                  dd       dz         D ]3  }|j                  | j                  |   | j                  |dz
     z
         5 g }d}t        dt	        |       d      D ]  }| ||dz    | j                  dz  k(  r|j                  |dz          n||   dk(  r|j                  |       |dz  }n||   dv r{d| j                  d|dz
  |      z
  }|dk(  r|j                  |||   z          n?|d	k(  r|j                  |dz   ||   z          n|dk(  r|j                  |d	z   ||   z          |dz  }n||   dkD  r|j                  |dz          	 d| j                  d||dz         z
  }||xx   |z  cc<    |S # t        $ r Y &w xY w)
zReturn full rf_table of the CodonSeq records.

        A full rf_table is different from a normal rf_table in that
        it translate gaps in CodonSeq. It is helpful to construct
        alignment containing frameshift.
        r8   r)   r   r&   Nr   g        )r'      )	r+   r;   r   r   r   r=   r   r   	Exception)r!   rD   relative_posr   full_rf_table	codon_numgap_statthis_lens           r   get_full_rf_tablezCodonSeq.get_full_rf_table   s    I%%c2.	a()q#dmmAB/0145 	IAa 04==Q3G GH	I	q#d)Q' 	AAA$--!"33$$QW-i(A-$$Q'Q	i(H4tzz#q1ua88q=!((\)-D)DE]!((Qi1H)HI]!((Qi1H)HIQ	i(1,$$QW-tzz#q!a%88Y'83')	0   s   &F;;	GGc                 v    |t         j                  d   }| j                         }| j                  |||d      S )z,Apply full translation with gaps considered.r&   F)rB   rC   r   rD   )r   r:   rT   rH   )r!   rB   rC   rP   s       r   full_translatezCodonSeq.full_translate   sH    $2215K..0~~##"	  
 	
r$   c                     t        |      dk7  st        |t              st        d|      t	        t        |       j                  |d      | j                        S )z;Return a copy of the sequence without the gap character(s).r&   zUnexpected gap character, r)   r   )r   r   r+   r   r
   r;   r   )r!   gaps     r   ungapzCodonSeq.ungap   sK    s8q=
3 49#ABBD	))#r2T]]KKr$   c                 N    | | t        |            S  | t        |      |      S )z&Get codon sequence from sequence data.rX   r*   )clsseqr   s      r   from_seqzCodonSeq.from_seq   s)     s3x= s3x(33r$   )r)   r8   N)N*NT)Nr_   )r8   r   )__name__
__module____qualname____doc__r   r3   r6   rH   rJ   rT   rV   rZ   classmethodr^    r$   r   r
   r
      sO    B&%P)>"
 KO2$h%N

L 4 4r$   r
   c                 0   | j                         }g }t        |      D ]  \  }}t        |t              rk|}	 t        ||dz            }t        | ||       }t        |      dk(  r|j                  |       X|j                  t        |j                                      t        | t        |      t        |      dz          dk(  r|j                  d       |j                  | t        |      t        |      dz            |S # t        $ r |dz   }Y w xY w)zAList of codons according to full_rf_table for counting (PRIVATE).r&   r   ---)	rT   	enumerater   r   
IndexErrorr+   r   r=   rZ   )codonseqrP   	codon_lstr   kstartend
this_codons           r   _get_codon_listrp      s   
 ..0MI-( <1aE -A./ XeC01J:!#  ,  Z%5%5%7!89#a&3q6A:./58U# Xc!fs1vz:;#<$    ai s   DDDNc           	      l   t        | t              rt        |t              rnDt        | t              r)t        |t              r| j                  } |j                  }nt	        d      t        | j                               t        |j                               k7  r@t        dt        | j                                dt        |j                                d      |d}n||dk7  rt        d      |d	vrd
dl}|j                  d| d       d}|t        j                  d   }t        |       }t        |      }g }	g }
t        ||      D ]1  \  }}d|vsd|vs|	j                  |       |
j                  |       3 t        t         t"        t$        d}|dk(  r ||   |	|
||      S  ||   |	|
||      S )a  Calculate dN and dS of the given two sequences.

    Available methods:
        - NG86  - `Nei and Gojobori (1986)`_ (PMID 3444411).
        - LWL85 - `Li et al. (1985)`_ (PMID 3916709).
        - ML    - `Goldman and Yang (1994)`_ (PMID 7968486).
        - YN00  - `Yang and Nielsen (2000)`_ (PMID 10666704).

    .. _`Nei and Gojobori (1986)`: http://www.ncbi.nlm.nih.gov/pubmed/3444411
    .. _`Li et al. (1985)`: http://www.ncbi.nlm.nih.gov/pubmed/3916709
    .. _`Goldman and Yang (1994)`: http://mbe.oxfordjournals.org/content/11/5/725
    .. _`Yang and Nielsen (2000)`: https://doi.org/10.1093/oxfordjournals.molbev.a026236

    Arguments:
     - codon_seq1 - CodonSeq or or SeqRecord that contains a CodonSeq
     - codon_seq2 - CodonSeq or or SeqRecord that contains a CodonSeq
     - w  - transition/transversion ratio
     - cfreq - Current codon frequency vector can only be specified
       when you are using ML method. Possible ways of
       getting cfreq are: F1x4, F3x4 and F61.

    zVcal_dn_ds accepts two CodonSeq objects or SeqRecord that contains CodonSeq as its seq!zfull_rf_table length of seq1 (z) and seq2 (z) are not the sameNF3x4MLz8cfreq can only be specified when you are using ML method)F1x4rr   F61r   zUnknown cfreq (zF). Only F1x4, F3x4 and F61 are acceptable. Used F3x4 in the following.r&   r8   )rs   NG86LWL85YN00)r   r
   r   r]   r   r   rT   r1   warningswarnr   r:   rp   zipr=   _ml_ng86_lwl85_yn00)
codon_seq1
codon_seq2methodrB   rl   cfreqry   seq1_codon_lstseq2_codon_lstseq1seq2r   j	dnds_funcs                 r   	cal_dn_dsr     s   . *h'Jz8,L	J		*z*i/P^^
^^
1
 	
 :'')*c*2N2N2P.QQ,S1M1M1O-P,Q Rj::<=>>PR
 	
 }		v~UVV++eW %R R	
  ..q1$Z0N$Z0NDDNN3 1qLs!|KKNKKN EFEJI~ y tUK@@ y tQ<<r$   c           	         t        | ||      \  }}t        |||      \  }}||z   dz  }||z   dz  }	ddg}
t        | |      D ]2  \  }}t        |
t        |||            D cg c]
  \  }}||z    }
}}4 |
d   |z  }|
d   |	z  }|dk  rt        dt	        dd|z  z
        z        }nd	}|dk  r!t        dt	        dd|z  z
        z        }||fS d	}||fS c c}}w )
z$NG86 method main function (PRIVATE).)rB   rl          @r   rB   r&   g      ?      UUUUUU?r'   )_count_site_NG86r{   _count_diff_NG86absr   )r   r   rl   rB   S_sites1N_sites1S_sites2N_sites2S_sitesN_sitesSNr   r   mnpspndSdNs                      r   r}   r}   b  s$   )$K1MHh)$K1MHh("c)G("c)G
QBD$ 
1!"&6q!&UV
aAE
 


 
AB	AB	EzCGbL 0112	EzCGbL 0112 r6M r6M
s   $Cc                 N   d}d}d}d}d}| D ]  }g g d}	|j                  dd      }|dk(  r!t        |      D ]  \  }
}|D ]  }||k(  r	||v r:||v r6t        |      }|||
<   d	j                  |      }|	d
   j	                  |       G||v r:||v r6t        |      }|||
<   d	j                  |      }|	d
   j	                  |       t        |      }|||
<   d	j                  |      }|	d   j	                  |         |j
                  |   }dx}}|	d
   D ]3  }||j                  v r||z  }|j
                  |   |k(  r||z  }/||z  }5 |	d   D ]3  }||j                  v r|dz  }|j
                  |   |k(  r|dz  }/|dz  }5 ||z   dz  }|||z  z  }|||z  z  } ||fS )a  Count synonymous and non-synonymous sites of a list of codons (PRIVATE).

    Arguments:
     - codon_lst - A three letter codon list from a CodonSeq object.
       This can be returned from _get_codon_list method.
     - k - transition/transversion rate ratio.

    r   AGTCr   r   r   r   )
transitiontransversionUr   rg   r)   r   r   r&   r   )r;   rh   r   rA   r=   r?   r>   )rk   rB   rl   S_siteN_sitepurine
pyrimidine
base_tuplerG   neighbor_codonr   r   r   codon_charsro   aathis_codon_N_sitethis_codon_S_siteneighbor
norm_consts                       r   r   r   {  sE    FFFJ%J ,1(*B?c3'E>e$ 	FDAq F6&[Q&["&u+K%&KN!#!5J"<077
C*_j"&u+K%&KN!#!5J"<077
C"&u+K%&KN!#!5J">299*E#F	F( &&u-011-&|4 	'H;222!Q&!**84:!Q&!!Q&!	' '~6 	'H;222!Q&!**84:!Q&!!Q&!	' (*;;q@
#j00#j00Y,1Z Fr$   c           
         t        | t              rt        |t              s$t        dt        |        dt        |       d      t	        |       dk7  st	        |      dk7  r$t        dt	        |        dt	        |       d      ddg}| dk(  s|dk(  r|S dt        fd	| D              st        d
|  d      t        fd|D              st        d| d      | |k(  r|S g }t        t        | |            D ]"  \  }}|d   |d   k7  s|j                  |       $ dd}t	        |      dk(  r,t        | || ||            D cg c]
  \  }}||z    }}}|S t	        |      dk(  rs|D ]l  }| d| ||   z   | |dz   d z   }	t        | || |	|d            D cg c]
  \  }}||z    }}}t        | ||	||d            D cg c]
  \  }}||z    }}}n |S t	        |      dk(  rt        t        g dd            }
g }|
D ]  }| d|d    ||d      z   | |d   dz   d z   }|d|d    ||d      z   ||d   dz   d z   }|j                  ||f       t        | || ||d            D cg c]
  \  }}||z    }}}t        | ||||d            D cg c]
  \  }}||z    }}}t        | ||||d            D cg c]
  \  }}||z    }}} |S c c}}w c c}}w c c}}w c c}}w c c}}w c c}}w )zCount differences between two codons, three-letter string (PRIVATE).

    The function will take multiple pathways from codon1 to codon2
    into account.
    z;_count_diff_NG86 accepts string object to represent codon (, 
 detected)r   %codon should be three letter string (r   rg   r   r   r   r   c              3   &   K   | ]  }|v  
 y wr   re   r   r   r   s     r   r   z#_count_diff_NG86.<locals>.<genexpr>       /1qJ/   *Unrecognized character detected in codon1 ! (Codons consist of A, T, C or G)c              3   &   K   | ]  }|v  
 y wr   re   r   s     r   r   z#_count_diff_NG86.<locals>.<genexpr>  r   r   *Unrecognized character detected in codon2 r&   c           	          dx}}t        t        t        |j                  j                  | |g                  dk(  r	||z  }||fS ||z  }||fS )z4Compare two codon accounting for different pathways.r   r&   )r   setmapr?   get)codon1codon2rB   weightsdnds         r   compare_codonz'_count_diff_NG86.<locals>.compare_codon  s^    KB3s;448866:JKLMQRRf 8O f8Or$   r   rM   N      ?)rB   r   r   r&   rM   gUUUUUU?r   r&   )r   r+   r   typer   r1   r    rh   r{   r=   r   r   )r   r   rB   r   diff_posr   rl   r   r   
temp_codonpaths	tmp_codonr,   tmp1tmp2r   s                  @r   r   r     s    fc"*VS*Afbfj:
 	
 6{a3v;!+VRF}J8
 	
 QB&E/	%J///8/0
 	
 ///8/0
 	
 	c&&12 	#DAqtqt|"	#	 x=A  ff+NAq AB h I] ]a #BQZ&)3fQUWoE
 !$%"JKPS!1 E  !$%&KPS!1 E Z I3 ]ai34EI f!~qt4vadQhj7IIFad|fQqTl2T!A$(*5EE  $. !$M&$GT!1 E  !$M$k'R!1 E  !$M$GT!1 E !, Ii s$   KK$
K*2K0K6K<c                    t        |      }ddg}ddg}ddg}| |z   D ]G  }||   }	|	D ];  }
|
dk(  r|dxx   dz  cc<   |
dk(  r|dxx   dz  cc<   )|
dk(  s/|dxx   dz  cc<   = I t        |      dz  t        |      dz  t        |      dz  g}dgdz  }t        | |      D ]B  \  }}|dk(  s
|dk(  s||k(  rt        |t        |||	            D cg c]
  \  }}||z    }}}D t        ||d
z        D cg c]
  \  }}||z   }}}|dd }|dd }t        ||      D cg c]7  \  }}dt	        ddd
|z  z
  |z
  z        z  dt	        ddd
|z  z
  z        z  z
  9 }}}|D cg c]  }dt	        ddd
|z  z
  z        z   }}d|d
   |d   z  |d
   |d
   |d
   z   z  z   z  |d   d|d
   z  z   z  }d|d
   |d   z  |d   |d   |d   z   z  z   z  d
|d   z  d|d   z  z   z  }||fS c c}}w c c}}w c c}}w c c}w )zlLWL85 method main function (PRIVATE).

    Nomenclature is according to Li et al. (1985), PMID 3916709.
    r   0r&   24r   r9   rg   )	fold_dictrM   Nr   r         ?g      ?)_get_codon_foldsumr{   _diff_codonr   )r   r   rl   rB   codon_fold_dictfold0fold2fold4rG   fold_numfLPQr   r   r   r   PQr   Br   r   s                          r   r~   r~   %  s   
 &k2OFEFEFE "5) 	ACxaAcaAcaA	 
Uc	3u:+SZ#-=>A
qBdD/ 	eOv6V3C  FFoNAq AB 		  AEN	+DAq!a%	+B	+
2AA
12A 1I	Aq 
Cq1q5y1}-..'SAPQE	AR=S1SS	A 	 677'SAE	*+	+7A7	
adQqTkAaDAaD1Q4K00	1QqTA!H_	EB	
adQqTkAaDAaD1Q4K00	1Q1XAaD5H	IBr6M! 
,	 	8s   G,9G2$<G8'G>c                 r    d }i }| j                   D ]  }d|vs ||| j                         ||<    d|d<   |S )zFClassify different position in a codon into different folds (PRIVATE).c                    h d}d}t        |       }t        |      D ]  \  }}|t        |      z
  }g }|D ]+  }	|	||<   	 |j                  |dj	                  |                - |j                  ||          dk(  r|dz  }nD|j                  ||          dv r|dz  }n(|j                  ||          dk(  r|d	z  }nt        d
      |||<    |S # t
        $ r |j                  d       Y w xY w)N>   r   r   r   r   r)   stopr   r   )r&   rM   r   r   r   z3Unknown Error, cannot assign the position to a fold)r   rh   r   r=   rA   r@   r   r1   )
rG   r?   basefoldcodon_base_lstr   b
other_baser   r   s
             r   find_fold_classz(_get_codon_fold.<locals>.find_fold_classU  s   #en- 	"DAqAJB &$%q!&IImBGGN,CDE& xxe,-2-./69-./14"I  !"N1'	"(    &IIf%&s   #CC*)C*r   rg   )r?   )rB   r   
fold_tablerG   s       r   r   r   R  sV    4 J** Re /{7P7P QJuR Jur$   c                 @   dx}x}x}x}x}}||    }	d}
d}t        t        | |            D ]  \  }\  }}||k7  rC||
v r?||
v r;|	|   dk(  r|dz  }n-|	|   dk(  r|dz  }n|	|   dk(  r|dz  }nt        d|	|   z        ||k7  rC||v r?||v r;|	|   dk(  r|dz  }n-|	|   dk(  r|dz  }n|	|   dk(  r|dz  }nt        d|	|   z        ||k7  s||
v r||v s
||v s||
v s|	|   dk(  r|dz  }|	|   dk(  r|dz  }|	|   dk(  r|dz  }t        d|	|   z         ||||||fS )	zCount number of different substitution types between two codons (PRIVATE).

    returns tuple (P0, P2, P4, Q0, Q2, Q4)

    Nomenclature is according to Li et al. (1958), PMID 3916709.
    r   r   r   r   r&   r   r   zUnexpected fold_num %d)rh   r{   r1   )r   r   r   P0P2P4Q0Q2Q4r   r   r   r   r   r   s                  r   r   r   w  s    #$#B##b#2#R HFJs6623 K	6Aq6qF{qF{{c!a!#a!#a"#;hqk#IJJ6qJ1
?{c!a!#a!#a"#;hqk#IJJ6&[Q*_!z/a6k{c!a!#a!#a"#;hqk#IJJ;K< BB##r$   c           
      	  0 ddl m} ddlm} dddddddddddddddg}t	        |      } |t
              } |t
              }	| |z   D ]  }
|
dk7  r9|d   |
d   xx   dz  cc<   |d   |
d   xx   dz  cc<   |d   |
d   xx   dz  cc<   ||
   }t        |      D ]1  \  }}|dk(  r||
|   xx   dz  cc<   |d	k(  s"|	|
|   xx   dz  cc<   3  t        |j                               }t        |	j                               }t        ||	      D ]  \  }}||   |z  ||<   |	|   |z  |	|<    t        | ||
      }t        ||      t        |	|      f}||d   z  ||d   z  z   ||z   z  }t        d      D ]K  }t        ||   j                               }||   j                         D ci c]  \  }}|||z   c}}||<   M  |t
              }t        |j                  j!                               |j"                  z   D ]  }d|vsd||<    | |z   D ]  }||xx   dz  cc<    t%        | ||||      \  }}}t%        || |||      \  }}}||z   dz  }||z   dz  }ddddddddddg}t        d      D ]#  }dD ]  }||   |   ||   |   z   dz  ||   |<    % ddg} t        | |      D ]2  \  }}t        | t'        |||
            D !"cg c]
  \  }!}"|!|"z    } }!}"4 | d   |z  }#| d   |z  }$t        |       ||z   z  }%t)        dd|$z  z
        t)        dd|#z  z
        z  }&dt)        dd|%z  z
        z  }'d0ddg}(t        d      D ]  })t        |j                  j!                               |j"                  z   D cg c]  }d|vr|
 }*}t+        |||&|*|      }+ ||+|'z        },g d}i }-t        | |      D ]4  \  }}|dk7  s|dk7  s|-j-                  ||fd       |-||fxx   dz  cc<   6 |-D ]>  }t/        |d   |d   |,|*|      }.t        ||.      D !"cg c]  \  }!}"|!|"|-|   z  z    }}!}"@ |d   |z  |d   |z  f|d   |z  |d   |z  ff}g }/t        ||      D ]"  \  }}.|/j1                  t        ||.d             $ |/d   dz  |z  ||z   z  |/d   dz  |z  ||z   z  z   }'|/d   |/d   z  }&t3        0fdt        |/|(      D              r|/d   |/d   fc S |/}( yc c}}w c c}"}!w c c}w c c}"}!w )zsYN00 method main function (PRIVATE).

    Nomenclature is according to Yang and Nielsen (2000), PMID 10666704.
    r   )defaultdictexpmr   r   r   r   rg   r&   rM   r   r   r   r   r   )rl   rB   r   r   r   h㈵>   r   r   r   r   T)tc              3   F   K   | ]  \  }}t        ||z
        k    y wr   )r   )r   r   r   	tolerances      r   r   z_yn00.<locals>.<genexpr>  s"     F$!Qs1q5zI%Fs   !N)collectionsr   scipy.linalgr  r   r   rh   r   valuesr{   _get_TV_get_kappa_tr   itemsr   r?   keysr>   _count_site_YN00r   r   _get_Q
setdefault_count_diff_YN00r=   r    )1r   r   rl   rB   r   r  fcodonr   	fold0_cnt	fold4_cntrG   r   r   r   f0_totalf4_totalr   TVk04kappatotpir   r   bfreqSN1r   r   bfreqSN2r   r   bfreqSNr   r   r   r   r   r   r,   wr  dSdN_pretemprk   r   r   codon_npathtvdSdNr  s1                                                   @r   r   r     sF   
 (! aaa(aaa(aaa(F
 &k2OC IC I )E>1IeAh1$1IeAh1$1IeAh1$"5)h' 	)DAqCx%(#q(#c%(#q(#		)) 9##%&H9##%&HIy) /1 |h.	! |h.	!/ 
t	5B	2&Y(C
DCACF!22x(7JKE 1X ?&)""$%,21IOO,=>DAqQCZ>q	? 
S	B+++0023k6M6MM a<BqE D[ 
1
#3dB%[$ Hh $4dB%[$ Hh ("a'G("a'GQQQ/qqqq1QRG1X B% 	BA%a[^hqk!n<AGAJqM	BB QBD$ 
1!"&6q!&UV
aAE
 

 
AB	ABB7W$%AA"A"$4 55AQ]##AI1vHb	  +3388:;k>U>UU
!| 
	 

 2uaK8QKdO 	)DAqEza5j&&1vq1QF#q(#	)  	BA!!A$!aKHB58R[ATQ!a+a.((ABA	B egor!uw/"Q%'/2a57?1SS "% 	5EArKKQd34	5GaK'!Ww%67$q'A+:Og;
 
 Gd1gF#dH2EFF7DG##=A ?,

 Bs   *S&S, S2S7
c                    d}d}ddg}d}t        | |      D ]d  \  }}d||fvst        ||      D ]I  \  }	}
|	|
k(  rn9|	|v r|
|v r|dxx   dz  cc<   n#|	|v r|
|v r|dxx   dz  cc<   n|dxx   dz  cc<   |dz  }K f |d   |z  |d   |z  fS )zGet TV (PRIVATE).

    Arguments:
     - T - proportions of transitional differences
     - V - proportions of transversional differences

    r   )r   r   r   rg   r&   )r{   )
codon_lst1
codon_lst2rB   r   r   r  sitesr   r   r   r   s              r   r  r    s     FJ
QBEj*5 ((FF+ 	16&[Q&[qEQJE*_jqEQJEqEQJE
	 qEEM2a55=))r$   c                    | d   | d   z   | d<   | d   | d   z   | d<   d| d   | d   z  | d   | d   z  z   z  d| d   | d   z  | d   z  | d   z  | d   | d   z  | d   z  | d   z  z   z  d|d   d| d   z  | d   z  z  z
  z  z   |d	   z
  d| d   | d   z  | d   z  | d   | d   z  | d   z  z   z  z  }d|d   d| d   z  | d   z  z  z
  }d
t        |      z  }d
t        |      z  }||z  dz
  }|du rCd| d   | d   z  | d   z  | d   | d   z  | d   z  z   |z  | d   | d   z  | d   | d   z  z   z  z   }|S d| d   z  | d   z  d|| d   z  z   z  d| d   z  | d   z  d|| d   z  z   z  z   d| d   z  | d   z  z   |z  }|S )zmCalculate kappa (PRIVATE).

    The following formula and variable names are according to PMID: 10666704
    r   r   Yr   r   RrM   r&   r   g      F   r   )	r  r  r  r   r   ar   kappaF84
kappaHKY85s	            r   r  r  2  sq   
 g3BsGg3BsG	RWr#wC2c7!223
sGbg3'"S'1g3"S')BsG34

 r!uBsGbg-..0	0 Q%	 
bg3"S')BsGbg,=3,GG	H		JA 	
BqEQC[2c7*++As1vAs1vA1uqyHEzsGbg3'"S'BsG*;bg*EE3"S')BsGbg,==? ?
  3K"S'!QBsG);%;<"S'kBsG#q8bg+='=>?"S'kBsG#$ 	
 r$   c                    t        |       t        |      k7  r"t        dt        |       t        |      fz        t        |       }d}d}d}|j                  }	|j                  }
i }t	        | |      D ]4  \  }}|dk7  s|dk7  s|j                  ||fd       |||fxx   dz  cc<   6 dx}}ddddddddddg}|j                         D ]  \  }}|d   }dx}}t        d      D ]  }|D ]  }||   |k(  r|d	| |z   ||dz   d	 z   }||
v r"||   }||   |v r
||v r||z  }n||   |v r	||v r||z  }|	|   |	|   k(  r||z  }|d   |xx   ||z  z  cc<   l||z  }|d   |xx   ||z  z  cc<     |||z  z  }|||z  z  } d|z  ||z   z  }||z  }||z  }|D ]/  }t        |j                               }|D ]  }||xx   |z  cc<    1 |||fS )
a  Site counting method from Ina / Yang and Nielsen (PRIVATE).

    Method from `Ina (1995)`_ as modified by `Yang and Nielsen (2000)`_.
    This will return the total number of synonymous and nonsynonymous sites
    and base frequencies in each category. The function is equivalent to
    the ``CountSites()`` function in ``yn00.c`` of PAML.

    .. _`Ina (1995)`: https://doi.org/10.1007/BF00167113
    .. _`Yang and Nielsen (2000)`: https://doi.org/10.1093/oxfordjournals.molbev.a026236

    z?Length of two codon_lst should be the same (%d and %d detected)r   r   r   rg   r   r&   r   N)
r   r1   r?   r>   r{   r  r  r   r   r  )r(  r)  r  rl   rB   r#   r   r   r   
codon_dictr   r$  r   r   r   r   freqSN
codon_pairnpathrG   SNposr   r   r   r   r   s                               r   r  r  U  s    :#j/)M:J01
 	

 ZFJ%J**J""DKJ
+ %1:!u*""Aq61-A1$% Ggaaa(aaa(F )..0 
E1	A8 	6C" 6:%!&tt!3eC!GI6F!F!T)N+:+
0BaKF3Z6)dfnaKFe$
>(BBKA1IdOv~5OKA1IdOv~5O!6	6$ 	1u91u9-. Vw01JzGzG _
 	AaDJD	 GV##r$   c                 	   t        | t              rt        |t              s$t        dt        |        dt        |       d      t	        |       dk7  st	        |      dk7  r$t        dt	        |        dt	        |       d      g d}| dk(  s|dk(  r|S dt        fd	| D              st        d
|  d      t        fd|D              st        d| d      | |k(  r|S g }t        t        | |            D ]"  \  }}|d   |d   k7  s|j                  |       $ dd}	t	        |      dk(  r/t        | |	| ||d   |            D 
cg c]
  \  }
}|
|z    }}
}|S t	        |      dk(  r+|D cg c]  }| d| ||   z   | |dz   d z    }}g }|D ]X  }t        t        |j                  | ||g            }||d   |d   f   ||d   |d   f   f}|j                  |d   |d   z         Z |D cg c]  }d|z  t        |      z   }}t        |      D ]}  \  }}| d| ||   z   | |dz   d z   }t        | |	| |||||   dz              D 
cg c]
  \  }
}|
|z    }}
}t        | |	| |||||   dz              D 
cg c]
  \  }
}|
|z    }}
} |S t	        |      dk(  rt        t        g dd            }g }g }|D ]  }
| d|
d    ||
d      z   | |
d   dz   d z   }|d|
d    ||
d      z   ||
d   dz   d z   }|j                  ||f       t        t        |j                  | |||g            }||d   |d   f   ||d   |d   f   ||d   |d   f   f}|j                  |d   |d   z  |d   z          |D cg c]  }d|z  t        |      z   }}t        |||      D ]  \  }}}t        | |	| |d   |d   ||dz              D 
cg c]
  \  }
}|
|z    }}
}t        | |	|d   |d   |d   ||dz              D 
cg c]
  \  }
}|
|z    }}
}t        | |	|d   ||d   ||dz              D 
cg c]
  \  }
}|
|z    }}
} |S c c}}
w c c}w c c}w c c}}
w c c}}
w c c}w c c}}
w c c}}
w c c}}
w )a&  Count differences between two codons (three-letter string; PRIVATE).

    The function will weighted multiple pathways from codon1 to codon2
    according to P matrix of codon substitution. The proportion
    of transition and transversion (TV) will also be calculated in
    the function.
    z;_count_diff_YN00 accepts string object to represent codon (r   r   r   r   r  rg   r   c              3   &   K   | ]  }|v  
 y wr   re   r   s     r   r   z#_count_diff_YN00.<locals>.<genexpr>  r   r   r   r   c              3   &   K   | ]  }|v  
 y wr   re   r   s     r   r   z#_count_diff_YN00.<locals>.<genexpr>  r   r   r   r   r&   c                 t   d}d}|j                   }|j                  }| |v s||v r.| |   |v r||   |v rdd|dgS | |   |v r||   |v rdd|dgS ddd|gS ||    ||   k(  r.| |   |v r||   |v r|dddgS | |   |v r||   |v r|dddgS d|ddgS | |   |v r||   |v rdd|dgS | |   |v r||   |v rdd|dgS ddd|gS )Nr   r   r   )r?   r>   )	r   r   diffrB   r   r   r   dicr   s	            r   count_TVz"_count_diff_YN00.<locals>.count_TV  sP   F#J++C**D~4$<6)fTlf.Dq&!,,D\Z/F4LJ4Nq&!,,q!V,,VF+$<6)fTlf.D"Aq!,,D\Z/F4LJ4N"Aq!,,vq!,,$<6)fTlf.Dq&!,,D\Z/F4LJ4Nq&!,,q!V,,r$   rM   Nr   r   r   )r   r+   r   r   r   r1   r    rh   r{   r=   r   r   r2   r   r   )r   r   r   rk   rB   r  r   r   rl   r@  r,   qr   	path_prob	codon_idxprobr   r   r   r   r   r   r   s                         @r   r  r    s    fc"*VS*Afbfj:
 	
 6{a3v;!+VRF}J8
 	

B &E/	%J///8/0
 	
 ///8/0
 	
 	c&&12 	#DAqtqt|"	#	-8 x=A  HVVXa[+$VWAq AB F I ]aKSTafQi/&Q/ATITI 4 Y__vq&6I!JK	)A,	!45q1yQR|9S7TU  a47!234 :CCAQY/CIC!(+ 1#BQZ&)3fQUWoE
 !$ "J;yQR|VWGW!1 E  !$ "J;yQR|VWGW!1 E n IG ]ai34EII 
>f!~qt4vadQhj7IIFad|fQqTl2T!A$(*5EE  $. Y__vtT66R!ST	ilIaL01ilIaL01ilIaL01
   a47!2T!W!<=
> :CCAQY/CICy)U; 1a !$HVQqT1Q4QQRUS!1 E  !$HQqT1Q41{1q5Q!1 E  !$HQqT61Q4QQRUS!1 E & IG
 U D0 Ds6   Q5Q!5Q&Q+Q1Q7Q<RRc                 F   ddl m} ddlm}  |       }t	        | |||      }t        | |      D ]  \  }}	d||	fvs|||	fxx   dz  cc<    t        |j                  j                               |j                  z   D cg c]  }d|vr|
 }
}|||
|fd} ||g d	d
dd      }|j                  \  }}}t        ||||
|      }dx}}t        |
      D ]_  \  }}t        |
      D ]L  \  }	}||	k7  s	 |j                  |   |j                  |   k(  r|||   |||	f   z  z  }n|||   |||	f   z  z  }N a ||z  }||z  }|||
|fd} ||ddgd
dd      }|j                  \  }}d}t        ||||
|      }dx}}t        |
      D ]_  \  }}t        |
      D ]L  \  }	}||	k7  s	 |j                  |   |j                  |   k(  r|||   |||	f   z  z  }n|||   |||	f   z  z  }N a |dz  }|dz  }||z  }||z  }||fS c c}w # t        $ r Y ,w xY w# t        $ r Y w xY w)z"ML method main function (PRIVATE).r   )Counter)minimizer   rg   r&   r   c           	      :    t        | d   | d   | d   ||||       S )z'Temporary function, params = [t, k, w].r   r&   rM   rk   rB   _likelihood_funcparamsr  	codon_cntrk   rB   s        r   funcz_ml.<locals>.func@  s7     !1I1I1I#
 
 	
r$   )r&   皙?rM   zL-BFGS-B)绽|=r  rQ  )rR  
   r  )r   boundstolc           	      4    t        | d   | d   d||||       S )z5Temporary function, params = [t, k]. w is fixed to 1.r   r&   r   rI  rJ  rL  s        r   func_w1z_ml.<locals>.func_w1j  s3     !1I1I#
 
 	
r$   rP  )rQ  rQ  r   r   )r	  rF  scipy.optimizerG  _get_pir{   r   r?   r  r>   xr  rh   r@   )r   r   cmethodrB   rF  rG  rN  r  r   r   rk   rO  opt_resr  rl   r!  r   SdNdc1c2rW  rhoSrhoNr   r   s                             r   r|   r|   -  s   #'	I	tW+	>BD$ #1Aq!f"# k//4467+:Q:QQa< 	
I  i[
 6G iiGAq!r1aK0AKB9% 2y) 	EArAv	"0048Q8QRT8UUbfqAw.. bfqAw..	 !GB!GB i[
 	
C)G 99DAqAr1aK0AOD49% 2y) 	EArAv	"0048Q8QRT8UU21a4 00 21a4 00	 	AIDAID	dB	dBr6MwT   T   s,   ?G?1A H#A H	HH	H H c                    i }|dk(  rddddd}| |z   D ]  }|dk7  s	|D ]  }||xx   dz  cc<     t        |j                               }|j                         D 	
ci c]  \  }	}
|	|
|z   }}	}
|j                  j	                         |j
                  z   D ]$  }d|vs||d      ||d      z  ||d      z  ||<   & |S |dk(  rdddddddddddddddg}| |z   D ]A  }|dk7  s	|d   |d   xx   dz  cc<   |d   |d   xx   dz  cc<   |d   |d   xx   dz  cc<   C t        d	      D ]K  }t        ||   j                               }||   j                         D 	
ci c]  \  }	}
|	|
|z   c}
}	||<   M t        |j                  j	                               |j
                  z   D ]-  }d|vs|d   |d      |d   |d      z  |d   |d      z  ||<   / |S |d
k(  r|j                  j	                         |j
                  z   D ]  }d|vsd||<    | |z   D ]  }|dk7  s	||xx   dz  cc<    t        |j                               }|j                         D 	
ci c]  \  }	}
|	|
|z   }}	}
|S c c}
}	w c c}
}	w c c}
}	w )zObtain codon frequency dict (pi) from two codon list (PRIVATE).

    This function is designed for ML method. Available counting methods
    (cfreq) are F1x4, F3x4 and F64.
    rt   r   r  rg   r&   r   rM   rr   r   ru   rP  )r   r  r  r?   r  r>   r   r   )r   r   r[  rB   r  r  r   cr  r   rl   s              r   rY  rY    s    
B&qqq1 	#AEz #A1INI#	# &--/")/8A!QW*88**//1K4K4KK 	CA!|qtvad|3fQqTlB1	C< I7 
F	 !!!,!!!,!!!,

  	%AEzq	!A$1$q	!A$1$q	!A$1$		%
 q 	CAfQi&&()C06q	0AB1AGBF1I	C k//4467+:Q:QQ 	LA!|q	!A$&)AaD/9F1IadOK1	L I 
E	**//1K4K4KK 	A!|1	  	AEz1
	 "))+%'XXZ0TQaSj00I? 9$ C 1s   I9%I?$Jc                 <   | |k(  ry| |j                   v s||j                   v ry| |vs||vryd}d}g }t        t        | |            D ]"  \  }	\  }
}|
|k7  s|j                  |	|
|f       $ t	        |      dk\  ry|j
                  |    |j
                  |   k(  r=|d   d   |v r|d   d   |v r|||   z  S |d   d   |v r|d   d   |v r|||   z  S ||   S |d   d   |v r|d   d   |v r||z  ||   z  S |d   d   |v r|d   d   |v r||z  ||   z  S |||   z  S )a   Q matrix for codon substitution (PRIVATE).

    Arguments:
     - i, j  : three letter codon string
     - pi    : expected codon frequency
     - k     : transition/transversion ratio
     - w     : nonsynonymous/synonymous rate ratio
     - codon_table: Bio.Data.CodonTable object

    r   r   r   rM   r&   )r>   rh   r{   r=   r   r?   )r   r   r  rl   r!  rB   r   r   r>  r   r_  r`  s               r   _qrf    s    	AvK###qK,C,C'C	"FJD Q+ %8B8KKB$% 4yA~  #{'@'@'CC71:DGAJ&$8r!u9!WQZ:%$q'!*
*Br!u9 a5L 71:DGAJ&$8q52a5= !WQZ:%$q'!*
*Bq52a5=  r!u9r$   c           
      t   ddl }t        |      }|j                  ||f      }t        |      D ]4  }t        |      D ]$  }	||	k7  s	t	        ||   ||	   | |||      |||	f<   & 6 d}
t        |      D ]/  }t        ||ddf          |||f<   	 |
| ||      |||f    z  z  }
1 ||
z  }|S # t        $ r Y Dw xY w)z*Q matrix for codon substitution (PRIVATE).r   Nr   )numpyr   zerosr   rf  r   r@   )r  rl   r!  rk   rB   nprQ   r   r   r   nucl_substitutionss              r   r  r    s    II
)Y'(A9 y! 	AAvaL)A,Aqk!Q$	 9 qAw<-!Q$	"Yq\"2qAwh"?? 	
AH  		s   B++	B76B7c           
      "   ddl m} t        |||||      } ||| z        }	d}
t        |      D ]^  \  }}t        |      D ]K  \  }}||f|v s|	||f   ||   z  dk  r|
|||f   dz  z  }
+|
|||f   t	        ||   |	||f   z        z  z  }
M ` |
S )z,Likelihood function for ML method (PRIVATE).r   r   )r
  r  r  rh   r   )r  rl   r!  r  rN  rk   rB   r  r   r   
likelihoodr   r_  r   r`  s                  r   rK  rK    s    !r1aK0AQUAJ9% N2y) 	NEArBx9$QT7RV#q()RH"5"99J)RH"5BrFQq!tW<L8M"MMJ	NN r$   __main__)run_doctest)rv   Nr&   Nr   )F)!rc   	itertoolsr   mathr   Bio.Datar   Bio.Seqr   Bio.SeqRecordr   r
   rp   r   r}   r   r   r~   r   r   r   r  r  r  r  r|   rY  rf  r  rK  r`   
Bio._utilsro  re   r$   r   <module>rv     s    #    #d4s d4N8A=R2;|dX*Z"J)$bk\*8 F@$FMjgT0f/d." z&M r$   