B
    b1                 @   s   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 ddlmZ ddlmZ ddddddZdddZdd Zdd Zdd Zdd Zdd Zd d! ZG d"d# d#eZG d$d% d%eZdS )&zBio.SeqIO support for the "xdna" file format.

The Xdna binary format is generated by Christian Marck's DNA Strider program
and also used by Serial Cloner.
    N)match)pack)unpack)BiopythonWarning)Seq)ExactPosition)FeatureLocation)
SeqFeature)	SeqRecord   )SequenceIterator)SequenceWriterDNARNAprotein)r   r            linearcircular)r   r   c             C   s&   |  |}t||k r"td| |S )z9Read the specified number of bytes from the given handle.z Cannot read %d bytes from handle)readlen
ValueError)handlelengthdata r   /lib/python3.7/site-packages/Bio/SeqIO/XdnaIO.py_read(   s    
r   c             C   s2   t dt| dd }t d| t| |d dS )zRead a Pascal string.

    A Pascal string comprises a single byte giving the length of the string
    followed by as many bytes.
    z>Br   r   z%dsASCII)r   r   decode)r   r   r   r   r   _read_pstring0   s    r!   c             C   s   t t| S )N)intr!   )r   r   r   r   _read_pstring_as_integer:   s    r#   c             C   s.   t | }|dkr&t| t|}||fS dS dS )a  Read an overhang specification.

    An overhang is represented in a XDNA file as:
      - a Pascal string containing the text representation of the overhang
        length, which also indicates the nature of the overhang:
        - a length of zero means no overhang,
        - a negative length means a 3' overhang,
        - a positive length means a 5' overhang;
      - the actual overhang sequence.

    Examples:
      - 0x01 0x30: no overhang ("0", as a P-string)
      - 0x01 0x32 0x41 0x41: 5' AA overhang (P-string "2", then "AA")
      - 0x02 0x2D 0x31 0x43: 3' C overhang (P-string "-1", then "C")

    Returns a tuple (length, sequence).

    r   )NNN)r#   r   abs)r   r   Zoverhangr   r   r   _read_overhang>   s
    r%   c             C   sZ   xTdd |  dD D ]<}td|}|r@| \}}|g||< qd|kr|g|d< qW dS )zParse the description field of a Xdna feature.

    The 'description' field of a feature sometimes contains several
    GenBank-like qualifiers, separated by carriage returns (CR, 0x0D).
    c             S   s   g | ]}t |d kr|qS )r   )r   ).0xr   r   r   
<listcomp>`   s    z._parse_feature_description.<locals>.<listcomp>z^([^=]+)="([^"]+)"?$"ZnoteN)splitr   groups)desc
qualifierslinemZqualvaluer   r   r   _parse_feature_descriptionY   s    
r2   c             C   s   t | }t | }t | pd}t| }t| }tdt| d\}}}	|rLd}
nd}
|| }}t |  t|d ||
d}i }|r|g|d< t|| t|||d}|j| d	S )
zRead a single sequence feature.Zmisc_featurez>BBxBr   r   )strandlabel)typer.   N)	r!   r#   r   r   r   r2   r	   featuresappend)r   recordnamer-   r6   startendZforwardZdisplayZarrowr4   locationr.   featurer   r   r   _read_featurel   s$    


r?   c                   s0   e Zd ZdZ fddZdd Zdd Z  ZS )XdnaIteratorzParser for Xdna files.c                s   t  j|ddd dS )a   Parse a Xdna file and return a SeqRecord object.

        Argument source is a file-like object in binary mode or a path to a file.

        Note that this is an "iterator" in name only since an Xdna file always
        contain a single sequence.

        bZXdna)modeZfmtN)super__init__)selfsource)	__class__r   r   rD      s    	zXdnaIterator.__init__c             C   s:   | d}|stdt|dk r*td| ||}|S )z9Start parsing the file, and return a SeqRecord generator.p   zEmpty file.z2Improper header, cannot read 112 bytes from handle)r   r   r   iterate)rE   r   headerrecordsr   r   r   parse   s    

zXdnaIterator.parsec             c   s  t d|\}}}}}}|dkr&td|tkr6tdt||d}	t||d}
|
dd }tt|	|
||d}t| rt| |jd< |t	krt	| |jd	< t
|d
d
krt| t| t dt|d
d }x|dkrt|| |d
8 }qW |V  dS )z.Parse the file and generate SeqRecord objects.z>BBB25xII60xI12xr   zUnsupported XDNA versionzUnknown sequence typer    )descriptionr:   idmolecule_typetopologyr   z>BN)r   r   
_seq_typesr   r    r+   r
   r   annotations_seq_topologiesr   r   r%   r?   )rE   r   rJ   versionZseq_typerQ   r   Z
neg_lengthZ
com_lengthZsequencecommentr:   r9   Znum_featuresr   r   r   rI      s,    

zXdnaIterator.iterate)__name__
__module____qualname____doc__rD   rL   rI   __classcell__r   r   )rG   r   r@      s   r@   c                   s0   e Zd ZdZ fddZdd Zdd Z  ZS )
XdnaWriterzWrite files in the Xdna format.c                s   t  j|dd dS )zInitialize an Xdna writer object.

        Arguments:
         - target - Output stream opened in binary mode, or a path to a file.

        wb)rB   N)rC   rD   )rE   target)rG   r   r   rD      s    zXdnaWriter.__init__c             C   s   t |}yt|}W n tk
r2   tddY nX yt| tdW n tk
r\   Y nX d| _|jd}|dkr~d}n.d|krd}n d	|krd
}nd|krd}nd}|jdddkrd}nd}|j|j	r|j}n|j	 d|j }| j
tdd||t|dt|d | j
t|j | j
|d | j
tdd | d | d dd |jD }t|jt| }|dkrtd| dt t|dkrt|d }td| t |dd }| j
tdt| x|D ]}	| |	jddgd  d}
xZ|	jD ]P}|dkr4q"x:|	j| D ],}t|
dkrZ|
d }
|
d||f  }
q@W q"W | |
 | |	j |	jjjd }|	jjj}d}|	jjd kr|| }}d}| t| | t| | j
td!|ddd | d" qW | jrtd#t dS )$a  Write the specified record to a Xdna file.

        Note that the function expects a list (or iterable) of records
        as per the SequenceWriter interface, but the list should contain
        only one record as the Xdna format is a mono-record format.
        zMust have one sequenceNzMore than one sequence foundFrP   r   r   r   r   r   r   r   rQ   r   r   rM   z>BBB25xII60xI11xB   r   z>B0c             S   s0   g | ](}t |jjtkrt |jjtkr|qS r   )r6   r=   r;   r   r<   )r&   fr   r   r   r(   0  s   z)XdnaWriter.write_file.<locals>.<listcomp>z	Dropping z features with fuzzy locationsz%Too many features, dropping the last r5    )r5   Ztranslationr)   z%s="%s"r3   z>BBBBz127,127,127z1Some annotations were truncated to 255 characters)iternextStopIterationr   _has_truncated_stringsrS   getrN   
startswithrO   r   writer   r   bytesseqencode_write_pstringr7   warningswarnr   r.   r6   r=   r;   Zpositionr<   r4   str)rE   rK   r9   rP   ZseqtyperQ   rV   r7   Zdropr>   rN   Zqnamevalr;   r<   r4   r   r   r   
write_file   s    







zXdnaWriter.write_filec             C   sJ   t |dkrd| _|dd }| jtdt | | j|d dS )z*Write the given string as a Pascal string.r_   TNz>Br   )r   rf   r   ri   r   rl   )rE   sr   r   r   rm   h  s
    zXdnaWriter._write_pstring)rW   rX   rY   rZ   rD   rr   rm   r[   r   r   )rG   r   r\      s
   	 r\   )rZ   rn   rer   Zstructr   r   ZBior   ZBio.Seqr   ZBio.SeqFeaturer   r   r	   ZBio.SeqRecordr
   Z
Interfacesr   r   rR   rT   r   r!   r#   r%   r2   r?   r@   r\   r   r   r   r   <module>   s4   

&I