
:>"^-              
   @   sm  d  Z  d d l m Z d d l m Z m Z d d l Z d d l m Z m	 Z	 d d l
 m Z d d l m Z d d l m Z d d	 l m Z m Z m Z d d
 l m Z d d l m Z d e j d e j d e j d e j d e j i Z d d d d i Z d d   Z d d   Z d d   Z  d d   Z! d d   Z" d d   Z# d d   Z$ Gd  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.
    )match)packunpackN)AlphabetBiopythonWarning)_read_header)Seq)SequenceWriter)
SeqFeatureFeatureLocationExactPosition)	SeqRecord)	as_handle            linearcircularc             C   s5   |  j  |  } t |  | k  r1 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   5/tmp/pip-build-ww9dw3qa/biopython/Bio/SeqIO/XdnaIO.py_read&   s    r   c             C   sC   t  d t |  d   d } t  d | t |  |   d j 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_pstring.   s    r    c             C   s   t  t |    S)N)intr    )r   r   r   r   _read_pstring_as_integer8   s    r"   c             C   s?   t  |   } | d k r7 t |  t |   } | | f Sd Sd 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   N)NN)r"   r   abs)r   r   Zoverhangr   r   r   _read_overhang<   s
    
r$   c             C   s{   xt d d   |  j  d  D D]V } t d |  } | rZ | j   \ } } | g | | <q d | k r | g | d <q Wd 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_descriptionW   s    #r1   c             C   s   t  |   } t  |   } t  |   p' d } t |   } t |   } t d t |  d   \ } } }	 | rr d }
 n d
 }
 | | } } t  |   t | d | d |
 } i  } | r | g | d <t | |  t | d | d | } | j j |  d	 S)zRead a single sequence feature.Zmisc_featurez>BBxBr   r   strandlabeltyper-   N)	r    r"   r   r   r   r1   r
   featuresappend)r   recordnamer,   r4   startendZforwardZdisplayZarrowr2   locationr-   featurer   r   r   _read_featurej   s$    !	
r>   c             c   s  t  |  d  l}  t |  d  } t d |  \ } } } } } } | d k rZ t d   | t k rr t d   t |  |  j d  } t |  |  j d  }	 |	 j d  d }
 t t	 | t |  d	 |	 d
 |
 d |
 } | t
 k r t
 | | j d <t |  j d   d k rrt |   t |   t d t |  d   d } x' | d k rqt |  |  | d 8} qKW| VWd QRXd S)zParse a Xdna file and return a SeqRecord object.

    Note that this is an "iterator" in name only since a Xdna file always
    contain a single sequence.
    rbp   z>BBB25xII60xI12xr   zUnsupported XDNA versionzUnknown sequence typer    descriptionr9   idtopologyr   z>BN)r   r   r   r   
_seq_typesr   r   r*   r   r   _seq_topologiesannotationsr   r   r$   r>   )r   headerversionr4   rD   r   Z
neg_lengthZ
com_lengthsequencecommentr9   r8   Znum_featuresr   r   r   XdnaIterator   s.    (

rL   c               @   s.   e  Z d  Z d Z d d   Z d d   Z d S)
XdnaWriterzWrite files in the Xdna format.c          
   C   s  | s t  d   t |  d k r0 t  d   | d } d |  _ t j | j j  } t | t j  rs d } n< t | t j	  r d } n! t | t j
  r d } n d } | j j d d	  d
 k r d } n d } | j j | j  r | j } n d j | j | j  } |  j j t d d | | t |  d t |  d   |  j j t | j  j d   |  j j | j d   |  j j t d d   |  j d  |  j d  d d   | j D } t | j  t |  } | d k rt j d j |  t  t |  d k rVt |  d } t j d j |  t  | d d  } |  j j t d t |    xa| D]Y}	 |  j |	 j j d d g  d  d }
 xh |	 j D]] } | d k rqxE |	 j | D]6 } t |
  d k r|
 d }
 |
 d | | f }
 qWqW|  j |
  |  j |	 j  |	 j j j d } |	 j j  j } d } |	 j j! d k r| | } } d } |  j t |   |  j t |   |  j j t d | d d d   |  j d  q|W|  j rt j d t  d S) zWrite the specified record to a Xdna file.

        Note that the function expects a list 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 sequencer   zMore than one sequence foundr   Fr   r   rD   r   r   z{} {}z>BBB25xII60xI11xB   r   z>B0c             S   sF   g  |  ]< } t  | j j  t k r t  | j j  t k r |  q Sr   )r4   r<   r:   r   r;   )r%   fr   r   r   r'     s   	z)XdnaWriter.write_file.<locals>.<listcomp>z)Dropping {} features with fuzzy locationsz'Too many features, dropping the last {}Nr3    translationr(   z%s="%s"z>BBBBz127,127,127z1Some annotations were truncated to 255 characters)zlabelztranslationr5   )"r   r   _has_truncated_stringsr   Z_get_base_alphabetseqZalphabet
isinstanceZDNAAlphabetZRNAAlphabetZProteinAlphabetrG   getrB   
startswithrC   formatr   writer   strencode_write_pstringr6   warningswarnr   r-   r4   r<   r:   positionr;   r2   )selfrecordsr8   ZalptypeZseqtyperD   rK   r6   Zdropr=   rB   qnamevalr:   r;   r2   r   r   r   
write_file   s    
								
"	#
"	
zXdnaWriter.write_filec             C   sg   t  |  d k r+ d |  _ | d d  } |  j j t d t  |    |  j j | j d   d S)z*Write the given string as a Pascal string.rN   TNz>Br   )r   rS   r   rY   r   r[   )r`   sr   r   r   r\   E  s
    	zXdnaWriter._write_pstringN)__name__
__module____qualname____doc__rd   r\   r   r   r   r   rM      s   yrM   )&ri   rer   structr   r   r]   ZBior   r   Z
Bio._utilsr   ZBio.Seqr   ZBio.SeqIO.Interfacesr	   ZBio.SeqFeaturer
   r   r   ZBio.SeqRecordr   ZBio.Filer   Zgeneric_alphabetZgeneric_dnaZgeneric_rnaZgeneric_proteinrE   rF   r   r    r"   r$   r1   r>   rL   rM   r   r   r   r   <module>   s0   				
&9