计算化学公社
标题:
新手求助:python求二面角代码应该怎么写
[打印本页]
作者Author:
Jerryluo
时间:
2019-4-18 00:03
标题:
新手求助:python求二面角代码应该怎么写
请问用python语言读取txt文件中的四个原子的xyz坐标,并求二面角代码应该怎么写,谢谢。比如txt文件中乙烷的二面角:H3-C1-C2-H4
6
C2H6
H1 -1.51326409 -0.45762891 -0.02447848
H2 -1.51324568 1.05557928 -0.89812999
H3 -2.93991852 0.55119428 -0.02447848
C1 -1.86991852 0.55118109 -0.02447848
C2 -1.35657630 1.27713737 1.23292649
H4 -1.71163265 2.28651046 1.23194897
H5 -1.71484541 0.77386893 2.10657638
H6 -0.28657811 1.27543068 1.23390524
作者Author:
zjxitcc
时间:
2019-4-18 00:53
可参考实例
https://dasher.wustl.edu/tinker/distribution/source/geometry.f
作者Author:
Mikasa
时间:
2019-4-18 08:41
供参考:
#!/usr/bin/env python
"""Dihedral angle calculation module.
K. Rother
Two functions are provided (see documentation of each function for
a more detailed description):
angle (v1,v2) - returns the angle between two 2D or 3D numpy arrays
(in radians)
dihedral (v1,v2,v3,v4) - returns the dihedral angle between four 3D vectors
(in degrees)
The vectors that dihedral uses can be lists, tuples or numpy arrays.
Scientific.Geometry.Vector objects behave differently on Win and Linux,
and they are therefore not supported (but may work anyway).
"""
__author__ = "Kristian Rother"
__copyright__ = "Copyright 2007-2016, The Cogent Project"
__contributors__ = ["Kristian Rother", "Sandra Smit"]
__credits__ = ["Janusz Bujnicki", "Daniel McDonald"]
__license__ = "GPL"
__version__ = "1.9"
__maintainer__ = "Kristian Rother"
__email__ = "krother@rubor.de"
__status__ = "Production"
from numpy import array, cross, pi, cos, sqrt, sum, arccos as acos
class DihedralGeometryError(Exception):
pass
class AngleGeometryError(Exception):
pass
def fix_rounding_error(x):
ROUND_ERROR = 1e-14 # fp rounding error: causes some tests to fail
# will round to 0 if smaller in magnitude than this
"""
If x is almost in the range 0-1, fixes it.
Specifically, if x is between -ROUND_ERROR and 0, returns 0.
If x is between 1 and 1+ROUND_ERROR, returns 1.
"""
if -ROUND_ERROR < x < 0:
return 0
elif 1 < x < 1 + ROUND_ERROR:
return 1
else:
return x
def norm(a):
"""Returns the norm of a matrix or vector
Calculates the Euclidean norm of a vector.
Applies the Frobenius norm function to a matrix
(a.k.a. Euclidian matrix norm)
a = numpy array
"""
return sqrt(sum((a * a).flat))
def scalar(v1, v2):
"""
calculates the scalar product of two vectors
v1 and v2 are numpy.array objects.
returns a float for a one-dimensional array.
"""
return sum(v1 * v2)
def angle(v1, v2):
"""
calculates the angle between two vectors.
v1 and v2 are numpy.array objects.
returns a float containing the angle in radians.
"""
length_product = norm(v1) * norm(v2)
if length_product == 0:
raise AngleGeometryError(
"Cannot calculate angle for vectors with length zero")
cosine = scalar(v1, v2) / length_product
angle = acos(fix_rounding_error(cosine))
return angle
def calc_angle(vec1, vec2, vec3):
"""Calculates a flat angle from three coordinates."""
if len(vec1) == 3:
v1, v2, v3 = map(create_vector, [vec1, vec2, vec3])
else:
v1, v2, v3 = map(create_vector2d, [vec1, vec2, vec3])
v12 = v2 - v1
v23 = v2 - v3
angl = angle(v12, v23) * 180.0 / pi
return angl
def create_vector2d(vec):
"""Returns a vector as a numpy array."""
return array([vec[0], vec[1]])
def create_vector(vec):
"""Returns a vector as a numpy array."""
return array([vec[0], vec[1], vec[2]])
def create_vectors(vec1, vec2, vec3, vec4):
"""Returns dihedral angle, takes four
Scientific.Geometry.Vector objects
(dihedral does not work for them because
the Win and Linux libraries are not identical.
"""
return map(create_vector, [vec1, vec2, vec3, vec4])
def dihedral(vec1, vec2, vec3, vec4):
"""
Returns a float value for the dihedral angle between
the four vectors. They define the bond for which the
torsion is calculated (~) as:
V1 - V2 ~ V3 - V4
The vectors vec1 .. vec4 can be array objects, lists or tuples of length
three containing floats.
For Scientific.geometry.Vector objects the behavior is different
on Windows and Linux. Therefore, the latter is not a featured input type
even though it may work.
If the dihedral angle cant be calculated (because vectors are collinear),
the function raises a DihedralGeometryError
"""
# create array instances.
v1, v2, v3, v4 = create_vectors(vec1, vec2, vec3, vec4)
all_vecs = [v1, v2, v3, v4]
# rule out that two of the atoms are identical
# except the first and last, which may be.
for i in range(len(all_vecs) - 1):
for j in range(i + 1, len(all_vecs)):
if i > 0 or j < 3: # exclude the (1,4) pair
equals = all_vecs[i] == all_vecs[j]
if equals.all():
raise DihedralGeometryError(
"Vectors #%i and #%i may not be identical!" % (i, j))
# calculate vectors representing bonds
v12 = v2 - v1
v23 = v3 - v2
v34 = v4 - v3
# calculate vectors perpendicular to the bonds
normal1 = cross(v12, v23)
normal2 = cross(v23, v34)
# check for linearity
if norm(normal1) == 0 or norm(normal2) == 0:
raise DihedralGeometryError(
"Vectors are in one line; cannot calculate normals!")
# normalize them to length 1.0
normal1 = normal1 / norm(normal1)
normal2 = normal2 / norm(normal2)
# calculate torsion and convert to degrees
torsion = angle(normal1, normal2) * 180.0 / pi
# take into account the determinant
# (the determinant is a scalar value distinguishing
# between clockwise and counter-clockwise torsion.
if scalar(normal1, v34) >= 0:
return torsion
else:
torsion = -torsion
if torsion == 360:
torsion = 0.0
return torsion
复制代码
作者Author:
Daniel_Arndt
时间:
2019-4-18 08:44
我之前写过一段awk代码,比较粗糙。你可以参考一下。
function Dihedral(x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4, norm1,x5,y5,z5,norm2,x6,y6,z6)
{
norm1=sqrt((y1*(z2-z3)+y2*(z3-z1)+y3*(z1-z2))*(y1*(z2-z3)+y2*(z3-z1)+y3*(z1-z2))+(z1*(x2-x3)+z2*(x3-x1)+z3*(x1-x2))*(z1*(x2-x3)+z2*(x3-x1)+z3*(x1-x2))+(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2))*(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2)))
x5 = (y1*(z2-z3)+y2*(z3-z1)+y3*(z1-z2))/norm1
y5 = (z1*(x2-x3)+z2*(x3-x1)+z3*(x1-x2))/norm1
z5 = (x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2))/norm1
norm2=sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)+(z3-z2)*(z3-z2))
x6 = (y5*(z3-z2)-(y3-y2)*z5)/norm2
y6 = (z5*(x3-x2)-(z3-z2)*x5)/norm2
z6 = (x5*(y3-y2)-(x3-x2)*y5)/norm2
return -atan2(x6*(y2*(z3-z4)+y3*(z4-z2)+y4*(z2-z3))+y6*(z2*(x3-x4)+z3*(x4-x2)+z4*(x2-x3))+z6*(x2*(y3-y4)+x3*(y4-y2)+x4*(y2-y3)),x5*(y2*(z3-z4)+y3*(z4-z2)+y4*(z2-z3))+y5*(z2*(x3-x4)+z3*(x4-x2)+z4*(x2-x3))+z5*(x2*(y3-y4)+x3*(y4-y2)+x4*(y2-y3)))
}
作者Author:
让你变成回忆
时间:
2019-4-18 10:15
基本思想就是求出两个平面的法向量(定义平面内两个向量,然后用叉乘算出法向量),再求两个法向量之间的夹角。
作者Author:
k64_cc
时间:
2019-4-18 10:22
def dihedral(a, b, c, d):
"""
Calculate the dihedral angle between abc surface and bcd surface (- pi ~ pi).
"""
na = np.cross(c - b, a - b)
nb = np.cross(b - c, d - c)
return np.arccos(np.abs(np.dot(na, nb)) / np.sqrt(np.power(na, 2).sum()) / np.sqrt(np.power(nb, 2).sum()))
没查过边界值,凑合用的。
作者Author:
highlight
时间:
2019-4-18 10:26
搬运
https://stackoverflow.com/questions/20305272/dihedral-torsion-angle-from-four-points-in-cartesian-coordinates-in-python
里面用 wiki 定义的那个
#!/bin/env python3.6
import numpy as np
def read_file(filename):
with open(filename, 'r') as f:
natom = int(f.readline())
f.readline()
coordinates = []
for _ in range(natom):
line = f.readline()
coordinate = line.split()[1:]
coordinates.append(coordinate)
return np.array(coordinates, dtype=float)
def dihedral(coordinates, a, b, c, d):
i = coordinates[a]
j = coordinates[b]
k = coordinates[c]
l = coordinates[d]
f, g, h = i-j, j-k, l-k
a = np.cross(f, g)
b = np.cross(h, g)
axb = np.cross(a, b)
cos = np.dot(a, b)
sin = np.dot(axb, g) / np.linalg.norm(g)
r = -np.arctan2(sin, cos)
return np.degrees(r)
if __name__ == "__main__":
c = read_file('C2H6.xyz')
print(dihedral(c, 2, 3, 4, 5))
复制代码
作者Author:
Jerryluo
时间:
2019-4-18 15:04
十分感谢大家!
作者Author:
我本是个娃娃
时间:
2019-7-15 13:02
(, 下载次数 Times of downloads: 43)
上传 Uploaded
点击下载Click to download
based on the blog:
http://sobereva.com/302
you can modify according to the case you faced.
欢迎光临 计算化学公社 (http://bbs.keinsci.com/)
Powered by Discuz! X3.3