B
    be                 @   s   d Z ddlmZ ddl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mZmZ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"Z"ddl#Z#eeG dd de$Z%dd Z&dd Z'dS )zd
Tool for parsing and writing OFF library files to and from dictionaries of
ResidueTemplate objects
    )print_function)OrderedDict)closingN   )Atom)
RAD_TO_DEG)AmberWarning)FileFormatType)ResidueTemplateResidueTemplateContainer)PROTEINNUCLEICSOLVENTUNKNOWN)periodic_table)genopen)string_typesadd_metaclass)rangec               @   s   e Zd ZdZedZedZedZedZ	edZ
edZedZed	Zed
ZedZedZedZedZedZedZedZedd Zedd Zedd Zedd Zedd ZdS )AmberOFFLibraryz_
    Class containing static methods responsible for parsing and writing OFF
    libraries
    z!!index *array *strz\s*"(\S*?)"\s*$z{!entry\.(\S*?)\.unit\.atoms *table *str *name *str *type *int *typex *int *resx *int *flags *int *seq *int *elmnt *dbl *chgzg!entry\.(\S*?)\.unit\.atomspertinfo *table *str *pname *str *ptype *int *ptypex *int *pelmnt *dbl *pchgz*!entry\.(\S*?)\.unit\.boundbox *array *dblz0!entry\.(\S*?)\.unit\.childsequence *single *intz)!entry\.(\S*?)\.unit\.connect *array *intzO!entry\.(\S*?)\.unit\.connectivity *table *int *atom1x *int *atom2x *int *flagsz`!entry\.(\S*?)\.unit\.hierarchy *table *str *abovetype *int *abovex *str *belowtype *int *belowxz'!entry\.(\S*?)\.unit\.name *single *strz>!entry\.(\S*?)\.unit\.positions *table *dbl *x *dbl *y *dbl *zzg!entry\.(\S*?)\.unit\.residueconnect *table *int *c1x *int *c2x *int *c3x *int *c4x *int *c5x *int *c6xzw!entry\.(\S*?)\.unit\.residues *table *str *name *int *seq *int *childseq *int *startatomx *str *restype *int *imagingxz;!entry\.(\S*?)\.unit\.residuesPdbSequenceNumber *array *intz,!entry\.(\S*?)\.unit\.solventcap *array *dblz?!entry\.(\S*?)\.unit\.velocities *table *dbl *x *dbl *y *dbl *zc          	   C   s2   t t| d}tj| r$dS dS Q R X dS )a,   Sees if an open file is an OFF library file.

        Parameters
        ----------
        filename : str
            The name of the file to see if it is an OFF file format

        Returns
        -------
        is_fmt : bool
            True if it is recognized as OFF, False otherwise
        rTFN)r   r   r   	_headerrematchreadline)filenamef r   2lib/python3.7/site-packages/parmed/amber/offlib.py	id_formatA   s    zAmberOFFLibrary.id_formatc             C   s  t | trt| d}d}n| }d}| }tj|s>tdt }| }tj	|}x4|r|r|
 d }d||< | }tj	|}qZW |stdxV|r| s| }qtj|}|std|
 d }t||||< | }qW |r|  |S )	a   Parses an Amber OFF library

        Parameters
        ----------
        filename : str or file-like iterable
            The file name or file object to parse. If it is an iterable, it will
            be exhausted

        Returns
        -------
        residues : OrderedDict {str : :class:`ResidueTemplate`}
            Dictionary pairing residue names with their :class:`ResidueTemplate`
            objects

        Raises
        ------
        ValueError if the first line does not match the file format. This line
        will be consumed

        IOError if filename is the name of a file that does not exist

        RuntimeError if EOF is reached prematurely or other formatting issues
        found
        r   TFzUnrecognized OFF file formatr   Nz#Unexpected EOF in Amber OFF libraryzExpected atoms table not found)
isinstancer   r   r   r   r   r   
ValueErrorr   _resregroupsRuntimeErrorstrip_sec1re_parse_residueclose)r   fileobj
own_handlelineZresiduesrematchnamer   r   r   parseV   s>    


 zAmberOFFLibrary.parsec       2      C   s  t |}d}t|}|  }x|d dkr| \}}}}	}
}}}t|}t|}t|}t|	}	t|
}
t|}t|}t|}t||||d}|	|d kr|| |d7 }t|}|	| |  }x|r|
 s|  }qW qW || |dkr*g }d}x$|D ]}|| |t|7 }q
W tj|}|sFtdn*| d |krptd| d |f |  }x*|d dkr|std|  }qzW tj|}|stdn*| d |krtd| d |f yTt|  
 }t|  
 }t|  
 }t|  
 }t|  
 }W n tk
r\   td	Y n0X |dkr|d
k rz|t9 }||||||g|_|  }tj|}|stdn*| d |krtd| d |f t|  
 }|d |krtd||d |f t n&t|ts:|t|d kr:td|  }tj|}|s^tdn*| d |krtd| d |f y$t|  
 }t|  
 }W n tk
r   tdY nX |dkr|dkr||d  |_n4|dkr$|dkr$|tdd |D k r$td|dkrH|dkrH||d  |_n<|dkr|dkr|tdd |D k rtd| t |  }t|jdkrtj|}|stdn*| d |krtd| d |f |  }x|d dkr| \}}}|  }|dkrt|d }t|d }x*t |D ]\}}||kr<|d8 }P q<W || } || !||  ||   n|!t|d t|d  qW tj"|}|stdn*| d |krtd| d |f |  }x|d dkr|  }qW tj#|}|s*tdn*| d |krTtd| d |f |   |  }tj$|}|stdn*| d |krtd| d |f xR|D ]J}xB|D ]:}|   \}!}"}#t|!t|"t|#  |_%|_&|_'qW qW |  }tj(|}|s"tdn*| d |krLtd| d |f xt)|D ]}dd |   D \}$}%}&}'}(})|$dkr|jdk	r|j||$d  k	rtd|%dkr|jdk	r|j||%d  k	rtdx8|&|'|(|)fD ](}|dkr q|j*||d   qW qVW |  }tj+|}|sDtdn*| d |krntd| d |f xt)|D ]}|   \}*}+},}-}}.t|*}*t|+}+t|-}-t|,},t|}t|.}.|,|- t|| krtd|,|- t|| |f t |d k	rt,|| _-nF|d!k	r*t.|| _-n0|d"k	r@t/|| _-n|d#k	rZtd$| t |dkrz|*|| _0qzW |  }tj1|}|	std%n*| d |k	rtd| d |f xt)|D ]}|   	qW |  }tj2|}|
std&n*| d |k
r,td| d |f |   |   |   |   |   |  }tj3|}|
sxtd&n*| d |k
rtd| d |f xP|D ]H}x@|D ]8}d'd |   D \}/}0}1|/|0|1  |_4|_5|_6
qW 
qW |dkr|S |S )(a  
        Parses the residue information out of the OFF file assuming the file
        is pointed at the first line of an atoms table section of the OFF file

        Parameters
        ----------
        fileobj : file-like
            Assumed to be open for read, this file is parsed until the *next*
            atom table is read
        name : str
            The name of the residue being processed right now
           r   !)atomic_numbertyper,   chargez!Expected pertinfo table not foundz,Found residue %s while processing residue %sz#Unexpected EOF in Amber OFF libraryz!Expected boundbox table not foundz'Error processing boundbox table entriesg333333	@z&Expected childsequence table not foundz9Unexpected childsequence (%d); expected %d for residue %szHchild sequence must be 1 greater than the number of residues in the unitz Expected connect array not foundz&Error processing connect table entriesc             s   s   | ]}t |V  qd S )N)len).0r   r   r   r   	<genexpr>  s    z1AmberOFFLibrary._parse_residue.<locals>.<genexpr>z(HEAD on multi-residue unit not supportedc             s   s   | ]}t |V  qd S )N)r3   )r4   r   r   r   r   r5     s    z9TAIL on multi-residue unit not supported (%s). Ignored...z%Expected connectivity table not foundz"Expected hierarchy table not foundz#Expected unit name string not foundz'Expected unit positions table not foundz,Expected unit residueconnect table not foundc             s   s   | ]}t |V  qd S )N)int)r4   xr   r   r   r5   Q  s    NzHEAD atom is not connect0zTAIL atom is not connect1z&Expected unit residues table not foundz7residue table predicted %d, not %d atoms for residue %spnw?zUnknown residue type "%s"z*Expected residue sequence number not foundz(Expected unit solventcap array not foundc             s   s   | ]}t |V  qd S )N)float)r4   r7   r   r   r   r5     s    )7r   r
   r   split_strip_enveloping_quotesr6   r<   r   appendZadd_atomr$   r3   r   _sec2rer   r#   r"   _sec3rer    r   box_sec4rewarningswarnr   r   _sec5reheadsumtailZatoms_sec6re	enumerateZadd_bond_sec7re_sec8re_sec9rexxxyxz_sec10rer   connections_sec11rer   r1   r   r   r,   _sec12re_sec13re_sec14revxvyvz)2r(   r,   Z	containerZnresZtemplr*   ZnamtypZtypxZresxflagsseqZelmntZchgatomZstart_atomsZrunsumresr+   ZhasboxZangleabcr9   rG   rI   ijflagZiiidxZ	start_idxr7   yzZc1Zc2Zc3Zc4Zc5Zc6ZresnameidnextstartZimgrX   rY   rZ   r   r   r   r&      s   















"




.
"
  










"
zAmberOFFLibrary._parse_residuec             C   s|   d}t |dst|d}d}t|  }|d x|D ]}|d|  q8W x|D ]}t|| |  qTW |rx|  dS )a   Writes a dictionary of ResidueTemplate units to a file in OFF format

        Parameters
        ----------
        lib : dict {str : :class:`ResidueTemplate`}
            Items can be either :class:`ResidueTemplate` or
            :class:`ResidueTemplateContainer` instances
        dest : str or file-like
            Either a file name or a file-like object to write the file to
        Fwriter:   Tz!!index array str
z "%s"
N)hasattrr   sortedkeysrl   r   _write_residuer'   )libdestr)   namesr,   r   r   r   rl     s    




 zAmberOFFLibrary.writec             C   s  t |tr"t|j}|| |}| d|j  xNt|D ]B\}}x8|D ]0}| d|j|j|d |jd |j	|j
f  qJW q<W | d|j  x0|D ](}x"|D ]}| d|j|jf  qW qW | d|j  |jdkr| d n| d	 |jd
 |jd   kr|jd kr8n n| d|jd
   ntd| d|jd   | d|jd   | d|jd   | d|jt|d f  | d|j  t|dkr| d nl|d jdk	r| d|d jjd   n
| d |d jdk	r$| d|d jjd   n
| d tdd |D r| d|j  d}xN|D ]F}x2|jD ](}| d|jj| |jj| f  qhW |t|7 }q\W | d|j  d}xVt|D ]J\}}| d|d   x,|D ]$}| d|d |f  |d7 }qW qW | d|j  | d|j  | d|j  x8|D ]0}x(|D ] }| d |j|j|jf  qRW qHW | d!|j  d}x|D ]}||t| d ddddg}	|jdk	r|jjd |	d< |jdk	r|jjd |	d< x2t|jdd D ]\}}
|
jd |	|d < qW | d"t|	  |t|7 }qW | d#|j  d}xt|D ]\}}|jtkr~d$}nL|jtkrd%}n:|jtkrd&}n(|jtkrd'}ntd(|j t d'}| d)|j|d dt| ||t || f  |t|7 }qdW | d*|j  xBt|D ]6\}}t|dkrH| d n| d|d   q&W | d+|j  | d | d,|j  xb|D ]Z}xR|D ]J}yd-|j!|j"|j#f }W n  t$k
r   | d. Y nX | | qW qW dS )/aG   Writes a residue to an open file handle

        Parameters
        ----------
        dest : file-like
            File object to write the residue information to
        res : :class:`ResidueTemplate` or :class:`ResidueTemplateContainer`
            The residue template (or template container) to write to the file
        zl!entry.%s.unit.atoms table  str name  str type  int typex  int resx  int flags  int seq  int elmnt  dbl chg
z" "%s" "%s" 0 %d 131072 %d %d %.6f
r.   z[!entry.%s.unit.atomspertinfo table  str pname  str ptype  int ptypex  int pelmnt  dbl pchg
z "%s" "%s" 0 -1 0.0
z"!entry.%s.unit.boundbox array dbl
Nz -1.000000
 0.0
 0.0
 0.0
 0.0
z
 1.000000
         z %f
z(Cannot write boxes with different anglesr   r   z,!entry.%s.unit.childsequence single int
 %d
z!!entry.%s.unit.connect array int
z 0
 0
z %d
z 0
c             s   s   | ]}t |d kV  qdS )r.   N)r3   )r4   r   r   r   r   r5     s    z1AmberOFFLibrary._write_residue.<locals>.<genexpr>zE!entry.%s.unit.connectivity table  int atom1x  int atom2x  int flags
z	 %d %d 1
zU!entry.%s.unit.hierarchy table  str abovetype  int abovex  str belowtype  int belowx
z "U" 0 "R" %d
z "R" %d "A" %d
z!entry.%s.unit.name single str
z "%s"
z4!entry.%s.unit.positions table  dbl x  dbl y  dbl z
z %.6g %.6g %.6g
zZ!entry.%s.unit.residueconnect table  int c1x  int c2x  int c3x  int c4x  int c5x  int c6x
z %d %d %d %d %d %d
zj!entry.%s.unit.residues table  str name  int seq  int childseq  int startatomx  str restype  int imagingx
r8   r9   r:   r;   zUnrecognized residue type %rz "%s" %d %d %d "%s" %d
z3!entry.%s.unit.residuesPdbSequenceNumber array int
z$!entry.%s.unit.solventcap array dbl
z5!entry.%s.unit.velocities table  dbl x  dbl y  dbl z
z
 %g %g %g
z 0.0 0.0 0.0
)%r   r
   r   r,   r?   rl   rK   r1   rf   r0   r2   rB   r#   r3   rG   rI   anyZbondsZatom1Zatom2rO   rP   rQ   rS   tupler   r   r   r   rD   rE   r   _imaging_atomrX   rY   rZ   AttributeError)rr   r_   Ztmprc   r   r^   baseZbondrb   ZconnZatr[   sr   r   r   rp     s    










.








&

  





zAmberOFFLibrary._write_residueN)__name__
__module____qualname____doc__recompiler   r!   r%   r@   rA   rC   rF   rJ   rL   rM   rN   rR   rT   rU   rV   rW   staticmethodr   r-   r&   rl   rp   r   r   r   r   r      s0   















B  r   c             C   sN   | d | d   krdks>n | d | d   kr:dkrJn n| dd S | S )z0 Strips the quotation marks enveloping a string r   "'r.   r   )Zinpr   r   r   r>   H  s    >r>   c       
      C   s   ddl m} d}d}x<t| D ] \}}|jdkr|}|r:P d}qW |dkrN|S dS | jt| df}tt| }x@t| D ]4\}}|j	dkrt
jt
j|j  ||< q~|j	||< q~W |||}|| }	t|	|	 jddS )	z
    Determines the imaging atom for the residue. If all atoms are hydrogen
    except 1, it is the heavy atom. Otherwise, it is the atom *closest* to the
    COM of the residue
    r   )center_of_massFr   r.   Trt   )Zaxis)Zparmed.geometryr   rK   r0   ZcoordinatesZreshaper3   npZzerosZmassptZMassZElementZargminrH   )
r_   r   Zfound_heavyZ	heavy_idxrc   r^   ZcoordsZmassesZcomZdiffr   r   r   ry   N  s*    
 

ry   )(r   Z
__future__r   collectionsr   
contextlibr   Znumpyr   Ztopologyobjectsr   Z	constantsr   
exceptionsr   Zformats.registryr	   Zmodeller.residuer
   r   r   r   r   r    r   r   Zutils.ior   Z	utils.sixr   r   Zutils.six.movesr   r   rD   objectr   r>   ry   r   r   r   r   <module>   s0       4