
    {Tiu                        d 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	 ddlm
Z
 dd	lmZ dd
lmZ ddlmZ  ej"                  de       	 	 	 	 	 	 	 ddZd ZddZ	 ddZd Zd Z	 ddZd Zedk(  rddlmZ  e        yy)z'Code for dealing with Codon Alignments.    N)Iterable)Mapping)BiopythonExperimentalWarning)BiopythonWarning)CodonAlignment)mktest)CodonSeq
CodonTable)	SeqRecordztBio.codonalign is an experimental module which may undergo significant changes prior to its future official release.c	           
         ddl m}	 t        | |	      st        d      t	        |       }
|T	 t	        |      }|
|kD  rt        d|
 d| d      t        |t              rd}nt        |t              rd}nt        d      t        |t              st        d	      t	        |      |
k\  rCt        |t              rn/i }|D ]&  }|j                  }||v rt        d
| d      |||<   ( |}d}nt        dt	        |       d|
 d      |dk(  rt        | |      }n|dk(  rt        |j                               }| D ch c]  }|j                   }}||z
  r#||z
  }t        ddj                  |       d      g }| D ]"  }|j!                  |||j                     f       $ n4|dk(  r/g }| D ](  }	 ||j                     }|j!                  ||   f       * |t(        j*                  d   }g }d}D ]{  }t-        |d   |d   ||||      }|s,t        d|d   j                   d|d   j                   d      t/        |d   |d   |||||      }|j!                  |       |d   dk(  szd}} |rt1        t3        |            S t1        |      S # t        $ r t        |      }t	        |      }Y zw xY wc c}w # t"        $ r( t%        d|j                   d       t'        d       Y -w xY w)a\  Build a codon alignment from protein alignment and corresponding nucleotides.

    Arguments:
     - pro_align  - a protein MultipleSeqAlignment object
     - nucl_seqs - an object returned by SeqIO.parse or SeqIO.index
       or a collection of SeqRecord.
     - corr_dict  - a dict that maps protein id to nucleotide id
     - complete_protein - whether the sequence begins with a start
       codon

    Return a CodonAlignment object.

    The example below answers this Biostars question: https://www.biostars.org/p/89741/

    >>> from Bio.Seq import Seq
    >>> from Bio.SeqRecord import SeqRecord
    >>> from Bio.Align import MultipleSeqAlignment
    >>> from Bio.codonalign import build
    >>> seq1 = SeqRecord(Seq('ATGTCTCGT'), id='pro1')
    >>> seq2 = SeqRecord(Seq('ATGCGT'), id='pro2')
    >>> pro1 = SeqRecord(Seq('MSR'), id='pro1')
    >>> pro2 = SeqRecord(Seq('M-R'), id='pro2')
    >>> aln = MultipleSeqAlignment([pro1, pro2])
    >>> codon_aln = build(aln, [seq1, seq2])
    >>> print(codon_aln)
    CodonAlignment with 2 rows and 9 columns (3 codons)
    ATGTCTCGT pro1
    ATG---CGT pro2

    r   )MultipleSeqAlignmentz:the first argument should be a MultipleSeqAlignment objectz2Higher Number of SeqRecords in Protein Alignment (z,) than the Number of Nucleotide SeqRecords (z) are found!   zBNucl Sequences Error, Unknown type to assign correspondence methodzHcorr_dict should be a dict that corresponds protein id to nucleotide id!zDuplicate key ''   zNumber of items in corr_dict (z*) is less than number of protein records ()Protein Record z, z= cannot find a nucleotide sequence match, please check the idzProtein record (z) is not in corr_dict!F)gap_charcodon_tablecomplete_protein
anchor_len and Nucleotide Record  do not match!)r   r   r   	max_scoreT)	Bio.Alignr   
isinstance	TypeErrorlentuple
ValueErrorr   r   dictidRuntimeErrorzipsetkeysjoinappendKeyErrorprintexitr   generic_by_id_check_corr_get_codon_recr   _align_shift_recs)	pro_align	nucl_seqs	corr_dictr   unknownr   r   r   r   r   pro_numnucl_numcorr_methoddrecordkeypro_nucl_pairnucl_idipro_iddiffpro_rec	codon_alnshiftpair	corr_span	codon_recs                              J/home/agent/.local/lib/python3.12/site-packages/Bio/codonalign/__init__.pybuildrF      s   X / i!56TUU )nG	&9~H
 XDWI N==EJlT  i)K	8,KT  )T*/  y>W$)W-' $F ))Cax(?3%q)ABB#AcF	$
 	K0Y0@ A;;B)1F  aIy1		inn&' )*1!$$**GG#D!$))D/!2 3A A 
 M$ G$$gy/D%EFG 
	  	@G#GJJ/   '9W+=!>?	@  ..q1IE   GG#-!
	 !$q'** .%%)!WZZL@ 
 'QQ!!1'#I Y'|q 9: /	:;;i((g  	&i(I9~H	&n +$  (4JKLQs)   J :J5.J:J21J2:-K+*K+c                     d}t        |  D ]Z  }t        t        |            dk(  r|dj                  t        |            z  }8|ddj                  t        |            z   dz   z  }\ |S )zFGenerate regular expression based on a given list of codons (PRIVATE). r   [])r$   r   r%   r'   )codonsregr<   s      rE   
_codons2rerM      sg    
C&\ /s1v;!2773q6?"C3Q(3..C	/
 J    c                 P   ddl m} t        | |      st        d      i }| j                  j                         D ]&  \  }}|j                  |g       j                  |       ( |j                         D ]  \  }}t        |      ||<    t        | j                        ||<   d||<   |S )a  Set up the regular expression of a given CodonTable (PRIVATE).

    >>> from Bio.Data.CodonTable import generic_by_id
    >>> p = generic_by_id[1]
    >>> t = _get_aa_regex(p)
    >>> print(t['A'][0])
    G
    >>> print(t['A'][1])
    C
    >>> print(sorted(list(t['A'][2:])))
    ['A', 'C', 'G', 'T', 'U', '[', ']']
    >>> print(sorted(list(t['L'][:5])))
    ['C', 'T', 'U', '[', ']']
    >>> print(sorted(list(t['L'][5:9])))
    ['T', 'U', '[', ']']
    >>> print(sorted(list(t['L'][9:])))
    ['A', 'C', 'G', 'T', 'U', '[', ']']

    r   r
   z;Input table is not a instance of Bio.Data.CodonTable objectz...)
Bio.Data.CodonTabler   r   r   forward_tableitems
setdefaultr(   rM   stop_codons)r   stopr3   r   aa2codoncodonaarK   s           rE   _get_aa_regexrY      s    ( /k:.UVVH ..446 2	rB#**512nn& *
F!&)* 7 78HTNHWOrN   c           	         ddl }t        | t              rt        |t              st        d      t	        |      }d}| j
                  D ]  }	|	|k7  s	|||	   z  } t        |j
                  j                         j                  |d            }
|j                  ||
      }|r|j                         dfS t        | j
                        j                  |d      }t        dt        |      |      D cg c]
  }||||z     }}t        |d         |k  r|d   |d   z   |d<   g }d}g }t        |      D ]9  \  }}t        |      }d}d}||k(  rR|D ]:  }	|r&|dk(  r!|t        |j                        z  }||d   z  }+|||	   z  }||d   z  }< |j                  ||
      }nH||kD  rCd}d}t        |t        |            D ]  }||||      z  }||d   z  } |j                  ||
      }|rZ|j!                  |j#                         |j%                         |f       ||k(  r|j!                  |       |j!                         ||k(  r|j!                  |       )|j!                         < dj'                  |      }|j                  ||
      }|r|j                         dfS d	}d}|r|d   d
   dk7  rdd
d|z  d
z
  d|z  dz
  dg}|d   }|D ]  }|dk(  rd} n||dv r	|dz  |z   }n |d|z  d
z
  d|z  dz
  fv r|dz  d|z  |z
  z
  }|d   d   k\  r|
|d   d   |z
  |d   d    }n|
d|d   d    }t)        ||||||      \  }}|z|dk7  s||d<    n dk(  r't+        j,                  d|j.                   t0               t        t        |      dz
        D ]  }||dz      d   ||   d   z
  d|z  z  }dj'                  |||   d
   ||dz      d
          }|
||   d   ||dz      d    }d}|dk7  rt)        ||||||      \  }}||dk7  r|g|||   d
   ||dz      d
    d}|dk(  st+        j,                  d|j.                   t0                |d   d
   dz   t        |      dz
  k(  r|d   }t        |      }dd
d|z  d
z
  d|z  dz
  dg}|D ]  }|dk(  rd} n|dv r	|dz  |z   }n |d|z  d
z
  d|z  dz
  fv r|dz  d|z  |z
  z
  }t        |
      |d   d   z
  k\  r|
|d   d   |d   d   |z    }n|
|d   d   d }t)        ||||||      \  }}||dk7  s|j3                          ||d<    n dk(  r't+        j,                  d|j.                   t0               dj'                  |      }|j                  ||
      }|r|j                         d
|fS t5        d| j.                   d|j.                   d      c c}w )znCheck if the nucleotide can be translated into the protein (PRIVATE).

    Expects two SeqRecord objects.
    r   NzB_check_corr accepts two SeqRecord object. Please check your input.rH   Xr   Tr      )r   r   z&first frameshift detection failed for z'middle frameshift detection failed for z%last frameshift detection failed for zProtein SeqRecord (z) and Nucleotide SeqRecord (z) do not match!)rer   r   r   rY   seqstrupperreplacesearchspanranger   	enumeraterM   start_codonsr(   startendr'   _get_shift_anchor_rewarningswarnr"   r   popr#   ) pronuclr   r   r   r   r_   aa2repro_rerX   nucl_seqmatchpro_seqr<   anchorsanchor_distance
anchor_posanchorthis_anchor_lenqcodonfncodonlast_qcodonlast_fcodonjfull_pro_refirst_anchorshift_id_posshift_val_lstsh_anc	shift_val
sh_nuc_lensh_nucs                                    rE   r-   r-      sH    c9%Zi-HP
 	
 +&EFgg  >eBiF  488>>#++Hb9:HIIfh'E

a  
 cgg,&&x438CL*3U
./GAZ)
 
 wr{j(!"+3GBK
"7+ #	/IAv!&kOFG
 *,  *B'AF*[-E-E"FF5:- eBi'FuSz)G* 		&(3 :-  z3v;7 .A5#33K5:-K. 		+x8!!5;;=%))+q"AB"j0MM&)MM+."j0MM'*MM+.G#	/H ggfo		+x0JJL!$$  LL
1a 0A 5!"Aq:~'91z>A;Mq Q !. I A~!% F*%/!^i%?
"q:~'91z>A;M&NN%/!^q:~	7Q%R
!!}Q':5!)&qM!,z9JqM!<L"
 "**<JqM!,<!=+?	5*l,(FL )fl %+q	-. R<MM@	J(
 3z?Q./ 'A.q1JqM!4DDZX	Aq)9Jq1u<Ma<P!QR!*Q-"2ZA5Fq5IJ>+?	5*l,(FL %&B,GMhF:a=+jQ.?.BC!Fr\MMA$''K($ "~a 1$Gq(88 "%f+'!+'!+! "/ I A~!% F*%4q%89%D
"O+a/O+a/'  &5q%8/);&
 8}z"~a'88JF!)&rN1-
2q0AJ0N"
 "**R.*;*=!>+?	5/<,(FL )fl

%+r
56 R<MM?yI(
 ''&/KIIk84E

a//")#&& 2--1WWI_F 
s   2Wc                 n   ddl }t        dd      D cg c]  }t        |       }}d|cxk  rd|z  dz
  k  rn nt        t        |             D ]  }	d}
t	        |       D ]'  \  }}||	k(  r|
||   dz   ||   z   d	z   z  }
 |
||   z  }
) |
d
z  }
|j                  |
|      }|sT|
j                  dd      j                  d
d      }
|dz  }|
|fc S  sd|fS y|d|z  dz
  d|z  dz
  fv rd|z  |z
  }t        dt        |             D ]  }	d}
t	        |       D ]H  \  }}||	dz
  k(  r||	k(  r-|
t        | |	dz
     | |	   ||||   j                               z  }
A|
||   z  }
J |
d
z  }
|j                  |
|      }|su|
j                  dd      j                  d
d      }
|dz  }|
|fc S  sd|fS yyc c}w )a  Find a regular expression matching a potentially shifted anchor (PRIVATE).

    Arguments:
     - sh_anc    - shifted anchor sequence
     - sh_nuc    - potentially corresponding nucleotide sequence
       of sh_anc
     - shift_val - 1 or 2 indicates forward frame shift, whereas
       3*anchor_len-1 or 3*anchor_len-2 indicates
       backward shift
     - aa2re     - aa to codon re dict
     - anchor_len - length of the anchor
     - shift_id_pos - specify current shift name we are at

    r   Na   k   r^   r   ^(?P<z>..*)$rH   r   r[   )	r_   rf   chrr   rg   rd   rc   _merge_aa2rerb   )r   r   r   rq   r   r   r_   r<   shift_idr   r{   krX   rt   s                 rE   rk   rk     sA     %b#/1A/H/9)q:~))s6{# 	,AF"6* (26eBi&08L3IIGSSFeBi'F	(
 cMFIIff-ER088bA!|++	, |##  
q:~)1z>A+=>	>
NY.	 q#f+& 	,AF"6* (2A:!Vlq1uq	! .446 F eBi'F( cMFIIff-ER088bA!|+++	,, |## 7 
?' 0s   F2c                    d }t        t        |||    ||   f            }|dk(  rdj                  t        |d   d         t        |d   d         z        }d|z   dz   }|d|d   d   z   d	z   dz   |d   d   z   d	z   dz   |z   d	z   dz   |d   d   z   d	z   dz   |d   d   z   d	z   z  }n|dk(  rdj                  t        |d   d         t        |d   d         z        }	dj                  t        |d   d         t        |d   d         z        }
d|z   dz   }|d|d   d   z   d	z   dz   |	z   d	z   dz   |
z   d	z   dz   |d   d   z   d	z   z  }d
z  }|S )zDMerge two amino acids based on detected frame shift value (PRIVATE).c                     g }d}| D ]K  }|dk(  rd}|j                  d       |dk(  rd}$|dk(  r|d   |z   |d<   5|dk(  s;|j                  |       M |S )Nr   rI   r[   rH   rJ   )r(   )re_aaaasmr<   s       rE   get_aa_from_codonrez)_merge_aa2re.<locals>.get_aa_from_codonre   sr     
	ACx

2cbb'A+Ba

1
	 
rN   r   rH   r   r   r   >rI   rJ   r   )listmapr'   r%   )aa1aa2r   rq   reidr   scodon	intersectscodonre
intersect1
intersect2s              rE   r   r     s'     #)E#Jc
+CDEFA~GGCq	!-F1IaL0AAB	D=3&Qil  Qil	
     	 Qil
   Qil 	
" 
aWWS1.VAYq\1BBC
WWS1.VAYq\1BBC
D=3&Qil  	
     	 Qil
 	
 OHOrN   c                    ddl }ddlm} |j                  j	                  |d      }	|d   }
|d   }t        |      }|dv rt        | j                  j	                  |d            dz  |
d   |
d   z
  k7  r&t        d| j                   d	|j                   d
      d}t               }| j                  D ]k  }|dk(  r|dz  }|r|dk(  r|	|
d   |
d   dz    }|j                  t        |j                        t        |j                                     sC|dz  }t        j                   d| j                   d| d| d|j                   d| dt"               |dk(  rt%        d|j                   d      ||z  }|dz  }|	|
d   d|z  z   |
d   d|dz   z  z    }|j                         j'                  |      |k7  r;|dz  }t        j                   d| j                  |||j                  |fz  t"               |dk(  rt%        d|j                   d      ||z  }|dz  }n t)        ||j                        S |dk(  rddlm}  |g       }g }|d   }t/        |j1                         j3                               }|D ]B  }|j5                  |j7                  |             |j5                  |j9                  |             D g }|j9                         }	 |j5                  |       |dz  }||v rx||j;                  |         j=                         rV|j;                  |      }d||   d   ||   d   z
  z
  }|j5                  |       |j5                  |dz   |z
         ||   d   }n=||v r9||j;                  |         j?                         r||j;                  |         d   }||jA                         k\  rnt               }d}| j                  D ]  }|dk(  r|dz  }|r|dk(  r|	|d   |d   dz    }|j                  t        |j                        t        |j                                     ra|dz  }t        j                   d| j                   d| d| d|j                   d| dt"               ||z  }|dz  }|t        | j                  j	                  dd            dz
  k  r4||dz      ||   z
  dz
  dk  r |dz  }||   }|dz
  z   }|}|	|| d|z  z   }n||   ||dz
     z
  dz
  dkD  rD|dz  }||dz
     dz   }||   }d||   ||dz
     z
  dz
  z
  }|	|| d|z  z   |	||   ||   dz    z   }nu||   }|dz   }|	|| }|j                         j'                  |      |k7  rC|dz  }t        j                   d| j                   d| d| d|j                   d| dt"               |dk(  rt%        d|j                   d      ||z  }|dz  } ||_!        t)        ||j                        S y)a3  Generate codon alignment based on regular re match (PRIVATE).

    span_mode is a tuple returned by _check_corr. The first element
    is the span of a re search, and the second element is the mode
    for the match.

    mode
     - 0: direct match
     - 1: mismatch (no indels)
     - 2: frameshift

    r   N)SeqrH   r   )r   r   r^   r   r   r   ----zstart codon of z ( z) does not correspond to r   zmax_score reached for z=! Please raise up the tolerance to get an alignment in anyway)tablez'%s(%s %d) does not correspond to %s(%s))r"   r   )deque   (z	Codon of )"r_   Bio.Seqr   r`   rc   rY   r   r    r"   r	   rd   rM   rh   ra   rb   rl   rm   r   r#   	translater   collectionsr   r   	groupdictr&   r(   re   ri   indexisupperislowerrj   rf_table)ro   rp   	span_moder   r   r   r   r_   r   rs   re   moderq   aa_num	codon_seqrX   
this_codonr   	shift_posshift_startrt   m_groupdictr<   r   shift_indexr   ri   rj   ngaps                                rE   r.   r.   ;  s    xx"-HQ<DQ<D+&Ev~swwx,-1d1gQ6GH!#&&)@	X  J	'' $	BSyU"	!fk%d1gQ!<
yy{778#j>N>N>P:Q NIMM)#&&B4q A))-	J<qB(
 >&0	 :F F  Z'	!%d1gF
&:T!WqFUVJGW=WX
##%//k/BbHNIMMA662vtww
CD(
 >&0	 :F F  Z'	!I$	J tww//	%"I	!5??,1134 	/AUZZ]+u{{1~.	/ KKMOOAFAKK0A0A!0D$E$M$M$O)//2;!7!:Y{=STU=V!VW	"A	 12k*1-k!k+2C2CA2F&G&O&O&Qk//23A6EIIK  J	'' 5	BSyU"	!fk%hqkHQK!OD
yy{778#j>N>N>P:Q NIMM)#&&2$ax @))-	:,aA(
 +IaKF Sb!9:Q>> !,x/??!CaGNI$V,E1y=1C$D!)%!4sTz!AJf%!(<<q@1DNI$VaZ014E"6*C 08FQJ3G G! KLD s+*%"8F#3hv6F6JKL  %V,E!)C!)%!4J!'')33+3F"L!Q	 'xqAfX >--1WWIQzl!E,
 >&0	 :F F  Z'	!k5	l &	tww//g 
rN   c           	      V   d }| D cg c]  }|j                   j                          }}dgt        |       z  }t        |       D ]w  \  }}|j                   j                         D ]U  }t	        |t
              r||xx   dz  cc<   !|j                   t        |      t        |      dz    dk(  sI||xx   dz  cc<   W y t        t        |            dk7  rt        d      d}t        |       }	 g }	 |D cg c]  }||   	 }	}t        |	      D ]f  \  }
}|j                  |
t        |      f       t	        |t              s4| |
   j                   t        |      t        |      dz    dk7  s_ ||||
         \  }}||z
  dz  dk7  rd||z
  dz  z
  }nd}|dk7  rdt        |      z  }t        | |
   j                   j                        }|| |
   j                   d	t        |       |z   | |
   j                   t        |      d	 z   z  }||
   }|j                  |      }|d	| ||dz   d	 D cg c]  }|t        |      z    c}z   }|||
<   || |
   _         |j                          |||z
  z  }||dz
  z  }i t        |      |k7  r|D ]  \  }
}t        | |
   j                   j                        }dt              z  }|| |
   j                   d	t        |       |z   | |
   j                   t        |      d	 z   z  }||
   }|j                  |      }g }t        dt        |      d      D ]  }|j                  ||z   d
z           |d	| |z   ||d	 D cg c]  }|t        |      z    c}z   }|||
<   || |
   _          |dz  }c c}w c c}w # t        $ r Y | S w xY wc c}w c c}w )zBuild alignment according to the frameshift detected by _check_corr (PRIVATE).

    Argument:
     - recs - a list of SeqRecords containing a CodonSeq dictated
       by a rf_table (with frameshift in some of them).

    c                 v    |j                  |       }d}	 t        |||z      t              r
|||z      |fS |dz  }&)Nr   r   )r   r   int)r   lstidxps       rE   find_next_intz(_align_shift_recs.<locals>.find_next_int  sI    iil#cAg,,37|Q&FA rN   r   r   r^   r   z3Number of alignable codons unequal in given recordsr   )r   Ng      @)r`   get_full_rf_tabler   rg   r   r   r%   r#   
IndexErrorr(   floatr	   r   r   rn   rf   )recsr   recfull_rf_table_lstrf_numr   r<   rec_numadd_lst
col_rf_lstr   r   r   gap_numgapsr`   full_rf_tablebpvinter_rfts                        rE   r/   r/     s    AEE224EES3t9_FD/ 3**, 	A!S!q	Q	Q#a&1*-6q	Q		 3v;1PQQ	A$iG
	(9:1!A$:J: j) 	DAqNNAs1v;'!U#QCFSVaZ(HE(Q$Q(9!(<=1EQ;!#1q5A+oGGa<W-D"DGKK,@,@AC47;;xQ047$q'++c!fh:OOOC$5a$8M&,,Q/B$1#2$62?Q2I:-.CL(: %M ,9%a("%DGK1q5 QU
+	, w<7" "1Q(<(<=S\)tAw{{8SV,t3d1gkk#a&(6KKK 1! 4"((+q#d)Q/ 1AOOAECK01 "#2&1>rs1CDAq3w<'DE 
 (5!!$!Q"  	
Q]  F  ; 	R KW	":* Es5   !N2N 6NN -N!N&N 	NN__main__)run_doctest)Nr   r]   NF
   r   )*r]   )Fr   )__doc__rl   collections.abcr   r   Bior   r   Bio.codonalign.codonalignmentr   r   Bio.codonalign.codonseqr	   Bio.Datar   Bio.SeqRecordr   rm   rF   rM   rY   r-   rk   r   r.   r/   __name__
Bio._utilsr    rN   rE   <module>r      s    .  $ # ,   8 0 ,  # @  j)ZF JL@FA$H;~ TVW0tM` z&M rN   