Source code for core.geometry

#!/usr/bin/env python
# coding: utf-8

# In[ ]:


from simtk import unit
import numpy as np

[docs]class geometry: """ A class to hold methods for calculating geometrical values given sets of atom coordinates. """
[docs] def position2Array(position, output_unit): """Converts an OpenMM position object quantity into a numpy array. Parameters ---------- position : simtk.unit.quantity.Quantity Array containing quantity objects [e.g. (x,y,z) array returned from positions]. output_unit : simtk.unit.unit.Unit Unit in which to return the items of the array. Returns ------- numpy.ndarray A numpy array containing the quantity values converted to floats. """ return np.array([c.value_in_unit(output_unit) for c in position])
[docs] def bond(coord1, coord2): """Calculate the distance length between two (x,y,z) quantity coordinates. Parameters ---------- coord1 : simtk.unit.quantity.Quantity array Vector for the first coordinate. coord2 : simtk.unit.quantity.Quantity array Vector for the second coordinate. Returns ------- simtk.unit.quantity.Quantity Quantity (value and unit) of the distance length in nanometers. """ coord1 = geometry.position2Array(coord1, unit.nanometer) coord2 = geometry.position2Array(coord2, unit.nanometer) bond_length = np.linalg.norm(coord2 - coord1) return bond_length * unit.nanometer
[docs] def angle(coord1, coord2, coord3): """Calculate the angle length between three (x,y,z) quantity coordinates. Parameters ---------- coord1 : simtk.unit.quantity.Quantity array Vector for the first coordinate. coord2 : simtk.unit.quantity.Quantity array Vector for the second coordinate. coord3 : simtk.unit.quantity.Quantity array Vector for the third coordinate. Returns ------- simtk.unit.quantity.Quantity Quantity (value and unit) of the angle length in radians. """ coord1 = geometry.position2Array(coord1, unit.nanometer) coord2 = geometry.position2Array(coord2, unit.nanometer) coord3 = geometry.position2Array(coord3, unit.nanometer) v1 = coord1 - coord2 v2 = coord3 - coord2 cos_theta = np.dot(v1, v2)/(np.linalg.norm(v1)*np.linalg.norm(v2)) angle = np.arccos(np.clip(cos_theta, -1, 1)) return angle * unit.radian
[docs] def torsion(coord1, coord2, coord3, coord4): """Calculate the torsion angle length between four (x,y,z) quantity coordinates. Parameters ---------- coord1 : simtk.unit.quantity.Quantity array Vector for the first coordinate. coord2 : simtk.unit.quantity.Quantity array Vector for the second coordinate. coord3 : simtk.unit.quantity.Quantity array Vector for the third coordinate. coord4 : simtk.unit.quantity.Quantity array Vector for the fourth coordinate. Returns ------- simtk.unit.quantity.Quantity Quantity (value and unit) of the torsion length in radians. """ coord1 = geometry.position2Array(coord1, unit.nanometer) coord2 = geometry.position2Array(coord2, unit.nanometer) coord3 = geometry.position2Array(coord3, unit.nanometer) coord4 = geometry.position2Array(coord4, unit.nanometer) v1 = coord2 - coord1 v2 = coord3 - coord2 v3 = coord4 - coord3 c1 = np.cross(v2, v3) c2 = np.cross(v1, v2) p1 = (v1 * c1).sum(-1) p1 *= (v2 * v2).sum(-1) ** 0.5 p2 = (c1 * c2).sum(-1) return np.arctan2(p1, p2) * unit.radian