B
    âêõb®2  ã               @   sÈ   d Z ddlmZmZm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mZ ddlmZ ddlmZ dZdZde ZeeƒG dd„ deƒƒZeeƒG dd„ deƒƒZdS )a  
Provides a class for parsing CHARMM-style coordinate files, namely CHARMM .crd
(coordinate) files and CHARMM .rst (restart) file. Uses CharmmFile class in
_charmmfile.py for reading files

Author: Jason Deckman
Contributors: Jason Swails
Date: June 19, 2015
é    )Úprint_functionÚdivisionÚabsolute_import)ÚclosingNé   )Úio)ÚFileFormatType)ÚCharmmError)Úunit)Úadd_metaclassÚstring_types)Úrange)ÚVec3é   gRO8à©?é   c               @   s\   e Zd ZdZedd„ ƒZdd„ Zedd„ ƒZedd	„ ƒZ	ed
d„ ƒZ
dd„ Zedd„ ƒZdS )ÚCharmmCrdFilea¥  
    Reads and parses a CHARMM coordinate file (.crd) into its components,
    namely the coordinates, CHARMM atom types, resid, resname, etc.

    Parameters
    ----------
    fname : str
        Name of the restart file to parse

    Attributes
    ----------
    natom : int
        Number of atoms in the system
    resname : list of str
        List of all residue names in the system
    coordinates : np.ndarray with shape (1, natom, 3)
        Atomic coordinates in a numpy array
    positions : natom x 3 distance Quantity
        2-D list of all coordinates with the appropriate distance unit attached.
        Has the format [ [x1, y1, z1], [x2, y2, z2], ... ]
    c          
   C   sJ  t t | ¡ƒ0}| ¡ }x |r:t| ¡ ƒdkr:| ¡ }qW d}x<|r|| ¡ }t| ¡ ƒdkrdd}qB|d dkrvd}qBd}qBW x |ržt| ¡ ƒdkrž| ¡ }q€W y€t| ¡ d ƒ}xjtt	|dƒƒD ]X}| ¡  ¡ }t|d ƒ t|d ƒ t
|d ƒ t
|d ƒ t
|d	 ƒ t
|d
 ƒ qÂW W n ttfk
r:   dS X dS Q R X dS )a   Identifies the file type as a CHARMM coordinate file

        Parameters
        ----------
        filename : str
            Name of the file to check format for

        Returns
        -------
        is_fmt : bool
            True if it is a CHARMM coordinate file
        r   TFÚ*é   r   é   é   é   é	   N)r   r   ÚgenopenÚreadlineÚlenÚstripÚintÚsplitr   ÚminÚfloatÚ
IndexErrorÚ
ValueError)ÚfilenameÚfÚlineÚintitleÚnatomÚrow© r(   ú7lib/python3.7/site-packages/parmed/charmm/charmmcrds.pyÚ	id_format2   s6    zCharmmCrdFile.id_formatc             C   sJ   g | _ g | _g | _g | _g | _g | _g | _g | _g | _d| _	|  
|¡ d S )Nr   )ÚatomnoÚresnoÚresnameÚresidÚatnameÚcoordsÚtitleÚsegidÚ	weightingr&   Ú_parse)ÚselfÚfnamer(   r(   r)   Ú__init__a   s    zCharmmCrdFile.__init__c             C   s   dd„ | j d D ƒtj S )zZ
        Atomic coordinates with units attached to them with the shape (natom, 3)
        c             S   s   g | ]}t |Ž ‘qS r(   )r   )Ú.0Úxyzr(   r(   r)   ú
<listcomp>t   s    z+CharmmCrdFile.positions.<locals>.<listcomp>r   )ÚcoordinatesÚuÚ	angstroms)r5   r(   r(   r)   Ú	positionso   s    zCharmmCrdFile.positionsc             C   s   | j S )N)r0   )r5   r(   r(   r)   r;   v   s    zCharmmCrdFile.coordinatesc             C   s   d S )Nr(   )r5   r(   r(   r)   Úboxz   s    zCharmmCrdFile.boxc          
   C   s  t t |d¡ƒê}| ¡  ¡ }xt|ƒdkr<| ¡  ¡ }q"W d}xH|rŠ| j |¡ | ¡  ¡ }t|ƒdkrrd}qD|d dkr„d}qDd}qDW xt|ƒdkr¨| ¡  ¡ }qŽW yt| 	¡ d ƒ| _
xÖt| j
ƒD ]È}| ¡  	¡ }| j t|d ƒ¡ | j t|d ƒ¡ | j |d ¡ | j |d ¡ | j t|d	 ƒ¡ | j t|d
 ƒ¡ | j t|d ƒ¡ | j |d ¡ | j |d ¡ | j t|d ƒ¡ qÌW d| j
 t| jƒks¶tdƒ‚W n" ttfk
rÚ   tdƒ‚Y nX t | j¡ d| j
df¡| _W d Q R X d S )NÚrr   TFr   r   r   r   r   r   r   é   é   r   z# atom mismatchz$Error parsing CHARMM coordinate fileéÿÿÿÿ)r   r   r   r   r   r   r1   Úappendr   r   r&   r   r+   r,   r-   r/   r0   r   r2   r.   r3   ÚAssertionErrorr!   r    r	   ÚnpÚarrayÚreshape)r5   r6   Úcrdfiler$   r%   r'   r(   r(   r)   r4   ~   sB    "zCharmmCrdFile._parsec             C   sð   t |tƒrt |d¡}d}nd}| d¡ | d¡ | dt| jƒ ¡ | jd jdkr\dnd| jd j }xrt	| jƒD ]d\}}|j
}|j ¡ pœ|j ¡ pœd	}| d
|d |j
j| |j
j|j|j|j|j||j
jdf
 ¡ qxW |rì| ¡  dS )aO   Writes a CHARMM coordinate file from a structure

        Parameters
        ----------
        struct : :class:`parmed.structure.Structure`
            The input structure to write the CHARMM coordinate file from
        dest : str or file-like object
            The file name or file object to write the coordinate file to
        ÚwTFz9* GENERATED BY PARMED (HTTPS://GITHUB.COM/PARMED/PARMED)
z*
z
%10d  EXT
r   r   ZSYSz=%10d%10d  %-8s  %-8s%20.10f%20.10f%20.10f  %-8s  %-8s%20.10f
N)Ú
isinstancer   r   r   Úwriter   ZatomsZresiduesZnumberÚ	enumerateZresiduer2   r   ÚchainÚnameZxxZxyZxzÚclose)ZstructÚdestZ
own_handleÚaddÚiZatomZresr2   r(   r(   r)   rL   ¨   s"    


$zCharmmCrdFile.writeN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr*   r7   Úpropertyr>   r;   r?   r4   rL   r(   r(   r(   r)   r      s   /*r   c               @   s†   e Zd ZdZedd„ ƒZdd„ Zedd„ ƒZedd	„ ƒZ	ed
d„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZdd„ Zddd„Zdd„ ZdS )ÚCharmmRstFileaq  
    Reads and parses data, velocities and coordinates from a CHARMM restart
    file (.rst) of file name 'fname' into class attributes

    Parameters
    ----------
    fname : str
        Name of the restart file to parse

    Attributes
    ----------
    natom : int
        Number of atoms in the system
    resname : list of str
        Names of all residues in the system
    coordinates : np.ndarray shape(1, natom, 3)
        List of all coordinates in the format [x1, y1, z1, x2, y2, z2, ...]
    coordinatesold : np.ndarray shape(1, natom, 3)
        List of all old coordinates in the format [x1, y1, z1, x2, y2, z2, ...]
    velocities : np.ndarray shape(1, natom, 3)
        List of all velocities in the format [x1, y1, z1, x2, y2, z2, ...]
    positions : natom x 3 distance Quantity
        2-D list of all coordinates with the appropriate distance unit attached.
        Has the format [ [x1, y1, z1], [x2, y2, z2], ... ]
    positionsold : natom x 3 distance Quantity
        2-D list of all old coordinates with the appropriate distance unit
        attached.  Has the format [ [x1, y1, z1], [x2, y2, z2], ... ]
    c          	   C   s,   t t | ¡ƒ}| ¡ }W dQ R X | d¡S )a   Identifies the file type as a CHARMM restart file

        Parameters
        ----------
        filename : str
            Name of the file to check format for

        Returns
        -------
        is_fmt : bool
            True if it is a CHARMM restart file
        NZREST)r   r   r   r   Ú
startswith)r"   r#   r$   r(   r(   r)   r*   æ   s    zCharmmRstFile.id_formatc             C   s\   g | _ g | _g | _g | _g | _g | _d| _d| _d| _d| _	d| _
d| _d| _|  |¡ d S )Nr   )Úheaderr1   ZenrgstatÚ	coordsoldr0   ÚvelsZ
ff_versionr&   ÚnprivÚnstepÚnsavcÚnsavvÚjhstrtr4   )r5   r6   r(   r(   r)   r7   ø   s    zCharmmRstFile.__init__c             C   s   | j S )N)r0   )r5   r(   r(   r)   r;   
  s    zCharmmRstFile.coordinatesc             C   s   | j S )N)r]   )r5   r(   r(   r)   Úcoordinatesold  s    zCharmmRstFile.coordinatesoldc             C   s   dd„ | j d D ƒtj S )z Atomic positions with units c             S   s   g | ]}t |Ž ‘qS r(   )r   )r8   r9   r(   r(   r)   r:     s    z+CharmmRstFile.positions.<locals>.<listcomp>r   )r0   r<   r=   )r5   r(   r(   r)   r>     s    zCharmmRstFile.positionsc             C   s   dd„ | j d D ƒtj S )z! Old atomic positions with units c             S   s   g | ]}t |Ž ‘qS r(   )r   )r8   r9   r(   r(   r)   r:     s    z.CharmmRstFile.positionsold.<locals>.<listcomp>r   )r]   r<   r=   )r5   r(   r(   r)   Úpositionsold  s    zCharmmRstFile.positionsoldc             C   s   | j S )z, Atomic velocities in Angstroms/picoseconds )r^   )r5   r(   r(   r)   Ú
velocities  s    zCharmmRstFile.velocitiesc             C   s   d S )Nr(   )r5   r(   r(   r)   r?   !  s    zCharmmRstFile.boxc             C   sP  t t |d¡ƒ4}d}x||r”| ¡ }t|ƒs6tdƒ‚| ¡ }| ¡ }t|ƒdkr‚|d dksj|d dkrpd}q’| j 	| ¡ ¡ q| j 	| ¡ ¡ qW xút
t| jƒƒD ]è}t| j|  ¡ ƒdkr¦| j|  ¡  ¡ }|d dd… d	ksú|d dd
… dkr¦yp| j|d   ¡  ¡ }t|d ƒ| _t|d ƒ| _t|d ƒ| _t|d ƒ| _t|d ƒ| _t|d ƒ| _P W q¦ ttfk
rŒ   tdƒ‚Y q¦X q¦W |  |d¡ |  || j¡ t | j¡ d| jdf¡| _|  |d¡ |  || j¡ t | j¡ d| jdf¡| _|  jt9  _|  |d¡ |  || j¡ t | j¡ d| jdf¡| _W d Q R X d S )Nr@   TzPremature end of filer   ZENERGIESz	!ENERGIESFr   ZNATOMr   z!NATOMr   r   r   r   zProblem parsing CHARMM restartz!XOLDrC   z!VXz!X)r   r   r   r   r   r	   r   r   r\   rD   r   r   r&   r_   r`   ra   rb   rc   r!   r    ÚscanÚ_get_formatted_crdsr]   rF   rG   rH   r^   ÚONE_TIMESCALEr0   )r5   r6   rI   ZreadingHeaderr$   Zwordsr'   r(   r(   r)   r4   %  sL    (zCharmmRstFile._parser   c             C   sh   d}|r|  d¡ xP|rb| ¡ }|s,tdƒ‚t| ¡ ƒdkr| ¡  ¡ d dt|ƒ… |krd}qW d S )NTr   zPremature end of fileF)Úseekr   r	   r   r   r   )r5   ZhandleÚstrr@   Zscanningr$   r(   r(   r)   rg   U  s     
 zCharmmRstFile.scanc             C   sž   x˜t | jƒD ]Š}| ¡ }|s$tdƒ‚t|ƒdt k r<tdƒ‚| dd¡}| t|dt… ƒ¡ | t|tdt … ƒ¡ | t|dt dt … ƒ¡ qW d S )NzPremature end of filer   zMLess than 3 coordinates present in coordinate row or coords may be truncated.ÚDÚEr   r   )	r   r&   r   r	   r   ÚCHARMLENÚreplacerD   r   )r5   rI   Zcrdsr'   r$   r(   r(   r)   rh   c  s    z!CharmmRstFile._get_formatted_crdsN)r   )rT   rU   rV   rW   rX   r*   r7   rY   r;   rd   r>   re   rf   r?   r4   rg   rh   r(   r(   r(   r)   rZ   Ç   s   0
rZ   )rW   Z
__future__r   r   r   Ú
contextlibr   ZnumpyrF   Zutilsr   Zformats.registryr   Ú
exceptionsr	   Ú r
   r<   Z	utils.sixr   r   Zutils.six.movesr   Zvec3r   rn   Z	TIMESCALEri   Úobjectr   rZ   r(   r(   r(   r)   Ú<module>	   s$    -