B
    bH2              ;   @   s  d 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mZmZmZmZ ddlZddl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d ZdZ de  d Z!edd Z"e"#d e  d d!e  d d"e  d d#e  d d$e  d d%e  d d&e  d d&e  d d'e  d d'e  d d(e  d d(e  d d)e  d d)e  d d*e  d d*e  d d+e  d d+e  d d,e  d d,e  d d-e  d d-e  d d.e  d d.e  d d/e  d d/e  d d0e  d d0e  d d1e  d d1e  d d2e  d d2e  d d3e  d d3e  d d4e  d d4e  d d5e  d d5e  d d6e  d d6e  d d7e  d d7e  d d8e  d d8e  d d#e  d d#e  d d!e  d d!e  d d9e  d d9e  d d:e  d d:e  d d;e  d d;e  d d<e  d d<e  d d=8 dS )>a}  
This module contains the functionality for carrying out geometrical calculations
for molecules and molecular systems

Author: Jason Swails
Contributors:

Copyright (C) 2014 - 2015  Jason Swails

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
    )division)defaultdict)unit)TINY
DEG_TO_RAD
RAD_TO_DEG)Vec3)picossinsqrtacosNc             C   s  t | r| t j} t |r,|t j}t |rB|t j}t |rX|t j}t |rn|t j}t |r|t j}|dt kr|dt kr|dt krtd |t9 }|t9 }|t9 }| ddg}|t	| }|t
| }||dg}	|t	| }
|t	|t	|t	|   t
| }t|| |
|
  ||  }|
||g}t|tk rbd|	d< t|tk rxd|	d< t|
tk rd|d< t|tk rd|d< t|tk rd|d< ||	|ft j S )a  
    This function takes the lengths of the unit cell vectors and the angles
    between them and returns 3 unit cell vectors satisfying those dimensions

    Parameters
    ----------
    a : double (or length Quantity)
        Length of the first unit cell vector
    b : double (or length Quantity)
        Length of the second unit cell vector
    c : double (or length Quantity)
        Length of the third unit cell vector
    alpha : double (or angle Quantity)
        Angle between vectors b and c
    beta : double (or angle Quantity)
        Angle between vectors a and c
    gamma : double (or angle Quantity)
        Angle between vectors a and b

    Returns
    -------
    list Quantity, list Quantity, list Quantity
        The 3, 3-element vectors as quantities with dimension length

    Notes
    -----
    The unit cell lengths are assumed to be Angstroms if no explicit unit is
    given. The angles are assumed to be degrees
       zIStrange unit cell vector angles detected. They appear to be in radians...g        r      )uis_quantityvalue_in_unit	angstromsdegreesr	   warningswarnr   r
   r   r   absr   )abcalphabetagammaavZbxZbyZbvZcxZcyZczZcv r   .lib/python3.7/site-packages/parmed/geometry.py!box_lengths_and_angles_to_vectors"   sH    
 
 
 
 
 
 $


$
     r!   c       	      C   s  t | r| t j} t |r,|t j}t |rB|t j}t| d | d  | d | d   | d | d   }t|d |d  |d |d   |d |d   }t|d |d  |d |d   |d |d   }t|d |d  |d |d   |d |d   ||  }t| d |d  | d |d   | d |d   ||  }t|d | d  |d | d   |d | d   ||  }|t9 }|t9 }|t9 }|||ft j |||ft j fS )aH  
    This function takes the lengths of the unit cell vectors and the angles
    between them and returns 3 unit cell vectors satisfying those dimensions

    Parameters
    ----------
    a : collection of 3 floats (or length Quantity)
        The first unit cell vector
    b : collection of 3 floats (or length Quantity)
        The second unit cell vector
    c : collection of 3 floats (or length Quantity)
        The third unit cell vector

    Returns
    -------
    (a, b, c), (alpha, beta, gamma)
        Two tuples, the first is the 3 unit cell vector lengths as
        length-dimension Quantity objects and the second is the set of angles
        between the unit cell vectors as angle-dimension Quantity objects

    Notes
    -----
    The unit cell lengths are assumed to be Angstroms if no explicit unit is
    given.
    r   r   r   )r   r   r   r   r   r   r   r   )	r   r   r   ZlaZlbZlcr   r   r   r   r   r    !box_vectors_to_lengths_and_anglesa   s     
 
 
 444<<<r"   c             C   s   t | r| t j} t |r,|t j}t |rB|t j}t|  } t| }t| }||t|d |d    }|| t|d | d    }|| t|d | d    }| ||fS )a  
    This function puts three unit cell vectors in a reduced form where a is
    "mostly" in x, b is "mostly" in y, and c is "mostly" in z. This form is
    necessary for some programs (notably OpenMM and Gromacs)

    Parameters
    ----------
    a : 3-element collection of float
        First unit cell vector
    b : 3-element collection of float
        Second unit cell vector
    c : 3-element collection of float
        Third unit cell vector

    Returns
    -------
    red_a, red_b, red_c : Vec3, Vec3, Vec3
        The reduced unit cell vectors in units of angstroms

    Notes
    -----
    The implementation here is taken from the OpenMM Python application layer
    written by Peter Eastman
    r   r   )r   r   r   r   r   round)r   r   r   r   r   r    reduce_box_vectors   s    


r$   c             C   s,   |  }| |jd df} tj| |ddS )a.   Compute the center of mass of a group of coordinates.

    Parameters
    ----------
    coordinates : numpy.ndarray
        Coordinate array
    masses : numpy.ndarray
        Array of masses

    Returns
    -------
    COM
        np.ndarray of shape (3,) identifying the cartesian center of mass

    Notes
    -----
    This method *requires* that the parameters be passed in as numpy arrays.
    AttributeError's will ensue if this is not the case. Also, coordinates must
    be able to be reshaped to (len(masses), 3), or ValueError's will ensue
    r      )ZweightsZaxis)ZflattenZreshapeshapenpZaverage)ZcoordinatesZmassesr   r   r    center_of_mass   s    r(   c             C   sL   t | \}}}t |\}}}|| }|| }	|| }
|| |	|	  |
|
  S )a   Computes the cartesian distance between two atoms. Ignores periodic boundary conditions.

    Parameters
    ----------
    a1, a2 : Atom or collection of 3 coordinates
        The two atoms between whom the distance should be calculated

    Returns
    -------
    d2 : float
        The square of the distance between the two atoms

    Notes
    -----
    This is done in pure Python, so it should not be used for large numbers of
    distance calculations. For that, use numpy-vectorized routines and the numpy
    coordinate arrays

    Raises
    ------
    TypeError if a1 or a2 are not Atom or iterable
    ValueError if a1 or a2 are iterable, but do not have exactly 3 items
    )_get_coords_from_atom_or_tuple)a1a2x1y1z1x2y2z2ZdxZdyZdzr   r   r    	distance2   s    r2   c             C   s   t | \}}}t |\}}}t |\}	}
}t|| || || g}t||	 ||
 || g}tt||}tt||}t||||  }tt|S )a   Computes the cartesian angle between three atoms. Ignores periodic boundary conditions.

    Parameters
    ----------
    a1, a2, a3 : Atom or collection of 3 coordinates
        The three atoms between whom the angle should be calculated (with a2
        being the central atoms)

    Returns
    -------
    ang : float
        The angle between the vectors a1-a2 and a2-a3 in degrees

    Notes
    -----
    This is done in pure Python, so it should not be used for large numbers of
    distance calculations. For that, use numpy-vectorized routines and the numpy
    coordinate arrays

    Raises
    ------
    TypeError if a1, a2, or a3 are not Atom or iterable
    ValueError if a1, a2, or a3 are iterable, but do not have exactly 3 items
    )r)   r'   arrayr   dotr   arccos)r*   r+   a3r,   r-   r.   r/   r0   r1   Zx3Zy3Zz3v1v2l1l2cosar   r   r    angle   s    r<   c             C   s   t t| t|t|t|g}|d |d  }|d |d  }|d |d  }t||}t||}	t t ||}
t t |	|	}t ||	|
|  }t ||dkrt t |S t t | S dS )a  
    Computes the angle between three vectors made up of four points (all three
    vectors share one point with one other vector)

    Parameters
    ----------
    a1, a2, a3, a4 : Atom or collection of 4 coordinates
        The four atoms between whom the torsion angle should be calculated (with
        a1 and a4 being the two end-point atoms not shared between two vectors)

    Returns
    -------
    dihed : float
        The measured dihedral between the 4 points in degrees
    r   r   r   r%   g        N)r'   r3   r)   _crossr   r4   r   r5   )r*   r+   r6   Za4pr7   r8   Zv3Zv1xv2Zv2xv3r9   r:   r;   r   r   r    dihedral  s    


r?   c             C   sd   t | d |d  | d |d   | d |d  | d |d   | d |d  | d |d   gS )z Computes the cross-product r   r   r   )r'   r3   )r7   r8   r   r   r    r=   6  s    "r=   c             C   s*   ddl m} t| |r&| j| j| jfS | S )Nr   )Atom)Zparmed.topologyobjectsr@   
isinstanceZxxZxyZxz)r   r@   r   r   r    r)   >  s    
r)   g?g?r   c               C   s   t S )N)_DEFAULT_CUTOFFr   r   r   r    <lambda>I      rC   gGz?gp=
ף?g333333?gGz?gGz@gffffff @gq=
ףp?g)\(?gQ?g
ףp=
?gq=
ףp?gQ?gzG?g?gq=
ףp?gQ?gRQ?g
ףp=
?gffffff?g(\?g\(\?gzG?g      ?gQ?gGz?g(\?g(\?g=
ףp= @g(\ @)8)r   r   )   rE   )   rF   )   rG   )   rH   )   rI   )r   rE   )rE   r   )r   rF   )rF   r   )r   rG   )rG   r   )r   rH   )rH   r   )r   rI   )rI   r   )rE   rF   )rF   rE   )rE   rG   )rG   rE   )rE   	   )rJ   rE   )rE   rH   )rH   rE   )rE   rI   )rI   rE   )rE      )rK   rE   )rE   #   )rL   rE   )rF   rG   )rG   rF   )rF   rJ   )rJ   rF   )rF   rH   )rH   rF   )rF   rI   )rI   rF   )rF   rK   )rK   rF   )rG   rJ   )rJ   rG   )rG   rH   )rH   rG   )rG   rI   )rI   rG   )rJ   rH   )rH   rJ   )rJ   rI   )rI   rJ   )rH   rI   )rI   rH   )rH   rK   )rK   rH   )rI   rK   )rK   rI   )$__doc__Z
__future__r   collectionsr   Zparmedr   r   Zparmed.constantsr   r   r   Zparmed.vec3r   Zmathr	   r
   r   r   r   Znumpyr'   r   r!   r"   r$   r(   r2   r<   r?   r=   r)   Z_OFFSETrB   ZSTANDARD_BOND_LENGTHS_SQUAREDupdater   r   r   r    <module>   sh   ?,+##	





