B
    b%                 @   sn   d Z ddlZddlmZ ddlmZ ddlmZ dZddd	Z	G d
d dZ
dd Zdd ZG dd dZdS )a  Classify protein backbone structure with Kolodny et al's fragment libraries.

It can be regarded as a form of objective secondary structure classification.
Only fragments of length 5 or 7 are supported (ie. there is a 'central'
residue).

Full reference:

Kolodny R, Koehl P, Guibas L, Levitt M.
Small libraries of protein fragments model native protein structures accurately.
J Mol Biol. 2002 323(2):297-307.

The definition files of the fragments can be obtained from:

http://github.com/csblab/fragments/

You need these files to use this module.

The following example uses the library with 10 fragments of length 5.
The library files can be found in directory 'fragment_data'.

    >>> from Bio.PDB.PDBParser import PDBParser
    >>> from Bio.PDB.FragmentMapper import FragmentMapper
    >>> parser = PDBParser()
    >>> structure = parser.get_structure("1a8o", "PDB/1A8O.pdb")
    >>> model = structure[0]
    >>> fm = FragmentMapper(model, lsize=10, flength=5, fdir="PDB")
    >>> chain = model['A']
    >>> res152 = chain[152]
    >>> res157 = chain[157]
    >>> res152 in fm # is res152 mapped? (fragment of a C-alpha polypeptide)
    False
    >>> res157 in fm # is res157 mapped? (fragment of a C-alpha polypeptide)
    True

    N)SVDSuperimposer)PDBException)	PPBuilderzlib_%s_z_%s.txt.c          	   C   s   |d t  | |f }t|}g }d}x|D ]x}|d dks,|d dkrJq,| }|d dkr|t||}	||	 |d7 }q,tdd |dd	 D }
|	d
|
 q,W W dQ R X |S )a  Read a fragment spec file (PRIVATE).

    Read a fragment spec file available from
    http://github.com/csblab/fragments/
    and return a list of Fragment objects.

    :param size: number of fragments in the library
    :type size: int

    :param length: length of the fragments
    :type length: int

    :param dir: directory where the fragment spec files can be found
    :type dir: string
    /r   *
   z------c             S   s   g | ]}t |qS  )float).0xr
   r
   5lib/python3.7/site-packages/Bio/PDB/FragmentMapper.py
<listcomp>^   s    z#_read_fragments.<locals>.<listcomp>   ZXXXN)_FRAGMENT_FILEopensplitFragmentappendnumpyZarrayadd_residue)sizelengthdirfilenamefpflistfidlZslfZcoordr
   r
   r   _read_fragments<   s     



r!   c               @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )r   z)Represent a polypeptide C-alpha fragment.c             C   s.   || _ d| _g | _t|dfd| _|| _dS )zInitialize fragment object.

        :param length: length of the fragment
        :type length: int

        :param fid: id for the fragment
        :type fid: int
        r   r   dN)r   counterresname_listr   Zzeros	coords_car   )selfr   r   r
   r
   r   __init__g   s
    
zFragment.__init__c             C   s   | j S )zcGet residue list.

        :return: the residue names
        :rtype: [string, string,...]
        )r$   )r&   r
   r
   r   get_resname_listy   s    zFragment.get_resname_listc             C   s   | j S )zcGet identifier for the fragment.

        :return: id for the fragment
        :rtype: int
        )r   )r&   r
   r
   r   get_id   s    zFragment.get_idc             C   s   | j S )zGet the CA coordinates in the fragment.

        :return: the CA coords in the fragment
        :rtype: Numeric (Nx3) array
        )r%   )r&   r
   r
   r   
get_coords   s    zFragment.get_coordsc             C   s<   | j | jkrtd| j| || j| j < | j d | _ dS )zAdd a residue.

        :param resname: residue name (eg. GLY).
        :type resname: string

        :param ca_coord: the c-alpha coorinates of the residues
        :type ca_coord: Numeric array with length 3
        zFragment boundary exceeded.r	   N)r#   r   r   r$   r   r%   )r&   resnameca_coordr
   r
   r   r      s
    	zFragment.add_residuec             C   s   | j S )zReturn lengt of the fragment.)r   )r&   r
   r
   r   __len__   s    zFragment.__len__c             C   s&   t  }|| j|j |  | S )zReturn rmsd between two fragments.

        :return: rmsd between fragments
        :rtype: float

        Examples
        --------
        This is an incomplete but illustrative example::

            rmsd = fragment1 - fragment2

        )r   setr%   runZget_rms)r&   otherZsupr
   r
   r   __sub__   s    zFragment.__sub__c             C   s   d| j | jf S )zRepresent the fragment object as a string.

        Returns <Fragment length=L id=ID> where L=length of fragment
        and ID the identifier (rank in the library).
        z<Fragment length=%i id=%i>)r   r   )r&   r
   r
   r   __repr__   s    zFragment.__repr__N)__name__
__module____qualname____doc__r'   r(   r)   r*   r   r-   r1   r2   r
   r
   r
   r   r   d   s   r   c       
      C   s   g }xt dt| | d D ]}t|d}xft d|D ]X}| ||  }| }|drb|d }ntd| rztd| }	|||	 q6W |	| qW |S )zDice up a peptide in fragments of length "length" (PRIVATE).

    :param pp: a list of residues (part of one peptide)
    :type pp: [L{Residue}, L{Residue}, ...]

    :param length: fragment length
    :type length: int
    r   r	   ZCA
CHAINBREAK)
rangelenr   Zget_resnameZhas_idr   Zis_disorderedZ	get_coordr   r   )
ppr   Z	frag_listir    jZresiduer+   Zcar,   r
   r
   r   _make_fragment_list   s    	


r>   c       	      C   sn   g }xd| D ]\}g }x4t dt|D ]"}|| }|| }|||f q"W |  |d d }|| q
W |S )a  Map flist fragments to closest entry in reflist (PRIVATE).

    Map all frgaments in flist to the closest (in RMSD) fragment in reflist.

    Returns a list of reflist indices.

    :param flist: list of protein fragments
    :type flist: [L{Fragment}, L{Fragment}, ...]

    :param reflist: list of reference (ie. library) fragments
    :type reflist: [L{Fragment}, L{Fragment}, ...]
    r   r	   )r9   r:   r   sort)	r   reflistZmappedr    Zrankr<   ZrfZrmsZfragmentr
   r
   r   _map_fragment_list   s    
rA   c               @   s2   e Zd ZdZdddZdd Zd	d
 Zdd ZdS )FragmentMapperzAMap polypeptides in a model to lists of representative fragments.      r   c             C   sZ   |dkrd| _ n|dkr d| _ ntd|| _|| _t|||| _|| _| | j| _dS )a  Create instance of FragmentMapper.

        :param model: the model that will be mapped
        :type model: L{Model}

        :param lsize: number of fragments in the library
        :type lsize: int

        :param flength: length of fragments in the library
        :type flength: int

        :param fdir: directory where the definition files are
                     found (default=".")
        :type fdir: string
        rD         r   z!Fragment length should be 5 or 7.N)	edger   flengthlsizer!   r@   model_mapfd)r&   rJ   rI   rH   Zfdirr
   r
   r   r'      s    zFragmentMapper.__init__c             C   s   t  }||}i }x|D ]}yt|| j}t|| j}xdtdt|D ]R}|| }	|| jk rbqHqH|t|| j krxqHqH|| j }
|
dkst	||
 ||	< qHW W q t
k
r } z|dkrn
t
|dW dd}~X Y qX qW |S )zjMap (PRIVATE).

        :param model: the model that will be mapped
        :type model: L{Model}
        r   r8   N)r   Zbuild_peptidesr>   rH   rA   r@   r9   r:   rG   AssertionErrorr   )r&   rJ   ZppbZpplrL   r;   r   Zmflistr<   resindexZwhyr
   r
   r   rK     s*    



 zFragmentMapper._mapc             C   s
   || j kS )zeCheck if the given residue is in any of the mapped fragments.

        :type res: L{Residue}
        )rL   )r&   rN   r
   r
   r   __contains__7  s    zFragmentMapper.__contains__c             C   s
   | j | S )z{Get an entry.

        :type res: L{Residue}

        :return: fragment classification
        :rtype: L{Fragment}
        )rL   )r&   rN   r
   r
   r   __getitem__>  s    zFragmentMapper.__getitem__N)rC   rD   r   )r3   r4   r5   r6   r'   rK   rP   rQ   r
   r
   r
   r   rB      s
   
$rB   )r   )r6   r   ZBio.SVDSuperimposerr   ZBio.PDB.PDBExceptionsr   ZBio.PDB.Polypeptider   r   r!   r   r>   rA   rB   r
   r
   r
   r   <module>+   s   
([