如何使用 MDAnalysis 对一组原子进行 principal_axes 和 moment_of_inertia?
How to use MDAnalysis to principal_axes and moment_of_inertia with a group of atoms?
我正在尝试使用 MDAnalysis (MDAnalysis.__version__ == 0.17.0
) API 函数 principal_axes()
和 moment_of_inertia()
来计算
这些矩阵用于一组选定的原子,如 doc:
中所述
import MDAnalysis
from MDAnalysis.tests.datafiles import PSF, DCD
import numpy as np
u = MDAnalysis.Universe(PSF, DCD)
CA = u.select_atoms("protein and name CA")
I = np.matrix(CA.moment_of_inertia())
U = np.matrix(CA.principal_axes())
print("center of mass", CA.center_of_mass())
print("moment of inertia", I)
print("principal axes", U)
print("Lambda = U'IU", np.transpose(U)*I*U)
输出:
center of mass [ 0.06873595 -0.04605918 -0.24643682]
moment of inertia [[ 393842.2070687 -963.01376005 -6050.68541811]
[ -963.01376005 474434.9289629 -3902.61617054]
[ -6050.68541811 -3902.61617054 520207.91703069]]
principal axes [[-0.04680878 -0.08278738 0.99546732]
[ 0.01813292 -0.9964659 -0.08201778]
[-0.99873927 -0.01421157 -0.04814453]]
Lambda = U'IU [[ 519493.24344558 -4093.3268841 11620.96444297]
[ -4093.3268841 473608.1536763 7491.56715845]
[ 11620.96444297 7491.56715845 395383.6559404 ]]
这看起来不对,原因之一是 U'IU
不是 doc 中提到的对角线:
也许我需要将蛋白质与质心对齐以计算相对于它的惯性矩。
问题是在文档中他们说 U'IU
,但 U 是 CA.principal_axes()
中 return 值的转置(参见 source code):
# Sort
indices = np.argsort(e_val)[::-1]
# Return transposed in more logical form. See Issue 33.
return e_vec[:, indices].T
Matlab 确认:
>> I=[ 393842.2070687 -963.01376005 -6050.68541811 ; -963.01376005 474434.9289629 -3902.61617054; -6050.68541811 -3902.61617054 520207.91703069];
>> U=[-0.04680878 -0.08278738 0.99546732; 0.01813292 -0.9964659 -0.08201778;-0.99873927 -0.01421157 -0.04814453];
>> U*I*U'
ans =
1.0e+05 *
5.2082 0.0000 -0.0000
0.0000 4.7413 -0.0000
-0.0000 -0.0000 3.9354
AtomGroup.principal_axes() 教程中的文档原则上是正确的,但令人困惑的是 AtomGroup.principal_axes()
的 return 值不是矩阵 U
而是它的转置, U.T
:
AtomGroup.principal_axes()
方法return是一个数组[p1, p2, p3]
,其中主轴p1
、p2
、p3
是长度数组3;为方便起见,选择了 行 向量的这种布局(以便可以使用 p1, p2, p3 = ag.principal_axes()
提取向量)。要形成一个矩阵 U
,其中主轴是 列向量 ,就像通常处理主轴一样,必须进行转置。例如:
import MDAnalysis
from MDAnalysis.tests.datafiles import PSF, DCD
import numpy as np
u = MDAnalysis.Universe(PSF, DCD)
CA = u.select_atoms("protein and name CA")
I = CA.moment_of_inertia()
UT = CA.principal_axes()
# transpose the row-vector layout UT = [p1, p2, p3]
U = UT.T
# test that U diagonalizes I
Lambda = U.T.dot(I.dot(U))
print(Lambda)
# check that it is diagonal (to machine precision)
print(np.allclose(Lambda - np.diag(np.diagonal(Lambda)), 0))
矩阵Lambda
应该是对角线(最后的print
应该显示True
):
[[ 5.20816990e+05 -6.56706349e-10 -2.83491351e-12]
[-6.62283524e-10 4.74131234e+05 -2.06979926e-11]
[-6.56687024e-12 -2.07159142e-11 3.93536829e+05]]
True
最后如果要计算"by hand":
values, evecs = np.linalg.eigh(I)
indices = np.argsort(values)
U = evecs[:, indices]
这给出 U
,其中主轴作为列向量。
我正在尝试使用 MDAnalysis (MDAnalysis.__version__ == 0.17.0
) API 函数 principal_axes()
和 moment_of_inertia()
来计算
这些矩阵用于一组选定的原子,如 doc:
import MDAnalysis
from MDAnalysis.tests.datafiles import PSF, DCD
import numpy as np
u = MDAnalysis.Universe(PSF, DCD)
CA = u.select_atoms("protein and name CA")
I = np.matrix(CA.moment_of_inertia())
U = np.matrix(CA.principal_axes())
print("center of mass", CA.center_of_mass())
print("moment of inertia", I)
print("principal axes", U)
print("Lambda = U'IU", np.transpose(U)*I*U)
输出:
center of mass [ 0.06873595 -0.04605918 -0.24643682]
moment of inertia [[ 393842.2070687 -963.01376005 -6050.68541811]
[ -963.01376005 474434.9289629 -3902.61617054]
[ -6050.68541811 -3902.61617054 520207.91703069]]
principal axes [[-0.04680878 -0.08278738 0.99546732]
[ 0.01813292 -0.9964659 -0.08201778]
[-0.99873927 -0.01421157 -0.04814453]]
Lambda = U'IU [[ 519493.24344558 -4093.3268841 11620.96444297]
[ -4093.3268841 473608.1536763 7491.56715845]
[ 11620.96444297 7491.56715845 395383.6559404 ]]
这看起来不对,原因之一是 U'IU
不是 doc 中提到的对角线:
也许我需要将蛋白质与质心对齐以计算相对于它的惯性矩。
问题是在文档中他们说 U'IU
,但 U 是 CA.principal_axes()
中 return 值的转置(参见 source code):
# Sort
indices = np.argsort(e_val)[::-1]
# Return transposed in more logical form. See Issue 33.
return e_vec[:, indices].T
Matlab 确认:
>> I=[ 393842.2070687 -963.01376005 -6050.68541811 ; -963.01376005 474434.9289629 -3902.61617054; -6050.68541811 -3902.61617054 520207.91703069];
>> U=[-0.04680878 -0.08278738 0.99546732; 0.01813292 -0.9964659 -0.08201778;-0.99873927 -0.01421157 -0.04814453];
>> U*I*U'
ans =
1.0e+05 *
5.2082 0.0000 -0.0000
0.0000 4.7413 -0.0000
-0.0000 -0.0000 3.9354
AtomGroup.principal_axes() 教程中的文档原则上是正确的,但令人困惑的是 AtomGroup.principal_axes()
的 return 值不是矩阵 U
而是它的转置, U.T
:
AtomGroup.principal_axes()
方法return是一个数组[p1, p2, p3]
,其中主轴p1
、p2
、p3
是长度数组3;为方便起见,选择了 行 向量的这种布局(以便可以使用 p1, p2, p3 = ag.principal_axes()
提取向量)。要形成一个矩阵 U
,其中主轴是 列向量 ,就像通常处理主轴一样,必须进行转置。例如:
import MDAnalysis
from MDAnalysis.tests.datafiles import PSF, DCD
import numpy as np
u = MDAnalysis.Universe(PSF, DCD)
CA = u.select_atoms("protein and name CA")
I = CA.moment_of_inertia()
UT = CA.principal_axes()
# transpose the row-vector layout UT = [p1, p2, p3]
U = UT.T
# test that U diagonalizes I
Lambda = U.T.dot(I.dot(U))
print(Lambda)
# check that it is diagonal (to machine precision)
print(np.allclose(Lambda - np.diag(np.diagonal(Lambda)), 0))
矩阵Lambda
应该是对角线(最后的print
应该显示True
):
[[ 5.20816990e+05 -6.56706349e-10 -2.83491351e-12]
[-6.62283524e-10 4.74131234e+05 -2.06979926e-11]
[-6.56687024e-12 -2.07159142e-11 3.93536829e+05]]
True
最后如果要计算"by hand":
values, evecs = np.linalg.eigh(I)
indices = np.argsort(values)
U = evecs[:, indices]
这给出 U
,其中主轴作为列向量。