o
    Rŀg                     @   s|   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ G d	d
 d
ejZG dd dejZdS )a  Bio.Align support for the "nexus" file format.

You are expected to use this module via the Bio.Align functions.

See also the Bio.Nexus module (which this code calls internally),
as this offers more than just accessing the alignment or its
sequences as SeqRecord objects.
    )StringION)	Alignment)
interfaces)Nexus)Seq)	SeqRecordc                       sV   e Zd ZdZdZd fdd	Z fddZddd	Zdd
dZdd Z	dd Z
  ZS )AlignmentWriterzNexus alignment writer.

    Note that Nexus files are only expected to hold ONE alignment
    matrix.

    You are expected to call this class via Bio.Align.write().
    r   Nc                    s   t  | || _dS )a2  Create an AlignmentWriter object.

        Arguments:
         - target     - output stream or file name
         - interleave - if None (default): interleave if columns > 1000
                        if True: use interleaved format
                        if False: do not use interleaved format

        N)super__init__
interleave)selftargetr   	__class__ C/var/www/html/myenv/lib/python3.10/site-packages/Bio/Align/nexus.pyr
   '   s   

zAlignmentWriter.__init__c                    s&   t  ||}|dkrtd| |S )zWrite a file with the alignments, and return the number of alignments.

        alignments - A list or iterator returning Alignment objects
           z'Expected to write 1 alignment; wrote %d)r	   
write_file
ValueError)r   stream
alignmentscountr   r   r   r   4   s   zAlignmentWriter.write_filec                 C   s&   t  }| ||| |d | S )a  Return a string with a single alignment in the Nexus format.

        Creates an empty Nexus object, adds the sequences
        and then gets Nexus to prepare the output.

         - alignment  - An Alignment object
         - interleave - if None (default): interleave if columns > 1000
                        if True: use interleaved format
                        if False: do not use interleaved format
        r   )r   write_alignmentseekread)r   	alignmentr   r   r   r   r   format_alignment>   s   
z AlignmentWriter.format_alignmentc                 C   s   |j \}}|dkrtd|dkrtd|j \}}|dkr"td|dkr*td| |}d| }	t|	}
t|j|D ]-\}}|dkrSd|jv rSt|j d|dkrdd	|jv rdt|j d
|
|j| q>|du rt|dk}|
j	||d dS )aC  Write a single alignment to the output file.

        - alignment  - An Alignment object
        - stream     - output stream
        - interleave - if None (default): interleave if columns > 1000
                       if True: use interleaved format
                       if False: do not use interleaved format
        r   zMust have at least one sequencez Non-empty sequences are requiredz?begin data; dimensions ntax=0 nchar=0; format datatype=%s; end;dnaUz contains U, but DNA alignmentrnaTz contains T, but RNA alignmentNi  r   )
shaper   _classify_mol_type_for_nexusr   zip	sequencesseqidadd_sequencewrite_nexus_data)r   r   r   r   nseqslengthrowscolumnsdatatypeminimal_recordnrecordaligned_sequencer   r   r   r   N   s.   
	


zAlignmentWriter.write_alignmentc                 C   s0   d}| j }|D ]}| j|||d |d7 }q|S )zWrite alignments to the output file, and return the number of alignments.

        alignments - A list or iterator returning Alignment objects
        r   r!   r   )r   r   )r   r   r   r   r   r   r   r   r   write_alignmentst   s   
z AlignmentWriter.write_alignmentsc                 C   sZ   dd |j D }tdd |D rdS tdd |D rdS tdd |D r)d	S td
)zReturn 'protein', 'dna', or 'rna' based on records' molecule type (PRIVATE).

        All the records must have a molecule_type annotation, and they must
        agree.

        Raises an exception if this is not possible.
        c                 S   s   h | ]	}|j d dqS )molecule_typeN)annotationsget).0sequencer   r   r   	<setcomp>   s    z?AlignmentWriter._classify_mol_type_for_nexus.<locals>.<setcomp>c                 s       | ]	}|o	d |v V  qdS )DNANr   r7   _r   r   r   	<genexpr>       z?AlignmentWriter._classify_mol_type_for_nexus.<locals>.<genexpr>r   c                 s   r:   )RNANr   r<   r   r   r   r>      r?   r   c                 s   r:   )proteinNr   r<   r   r   r   r>      r?   rA   z$Need the molecule type to be defined)r%   allr   )r   r   valuesr   r   r   r#      s   z,AlignmentWriter._classify_mol_type_for_nexus)N)__name__
__module____qualname____doc__fmtr
   r   r   r   r3   r#   __classcell__r   r   r   r   r      s    


&r   c                   @   s$   e Zd ZdZdZdd Zdd ZdS )AlignmentIteratorzNexus alignment iterator.r   c                 C   s>   zt |}W n ty   tdd w | dkrtdd S )NzEmpty file.z#NEXUSz&File does not start with NEXUS header.)nextStopIterationr   strip)r   r   liner   r   r   _read_header   s   
zAlignmentIterator._read_headerc           	         s   t  |js
d S tjtjksJ jdv r ddi njdkr*ddi njdkr4ddi nd  fddjD }t|\}} fd	dt|jD }t	
|d
d}t	|dkd d
 }t	||d
}t||}|S )N)r   
nucleotider4   r;   r   r@   rA   c                    s   g | ]	}t  j| qS r   )bytesmatrix)r7   name)r0   r   r   
<listcomp>   s    z:AlignmentIterator._read_next_alignment.<locals>.<listcomp>c                    s"   g | ]\}}t t|| d qS ))r'   r5   )r   r   )r7   r&   rS   )r5   r   r   rT      s    r   r   )r   rR   lenunaltered_taxlabels	taxlabelsr.   r   parse_printed_alignmentr$   npdiffmaxnonzerodelete)	r   r   aligned_seqsseqscoordinatesrecordsstepsindicesr   r   )r5   r0   r   _read_next_alignment   s*   









z&AlignmentIterator._read_next_alignmentN)rD   rE   rF   rG   rH   rO   rd   r   r   r   r   rJ      s
    	rJ   )rG   ior   numpyrY   	Bio.Alignr   r   	Bio.Nexusr   Bio.Seqr   Bio.SeqRecordr   r   rJ   r   r   r   r   <module>   s   	z