Coverage for /builds/ase/ase/ase/build/rotate.py : 100.00%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import numpy as np
4def rotation_matrix_from_points(m0, m1):
5 """Returns a rigid transformation/rotation matrix that minimizes the
6 RMSD between two set of points.
8 m0 and m1 should be (3, npoints) numpy arrays with
9 coordinates as columns::
11 (x1 x2 x3 ... xN
12 y1 y2 y3 ... yN
13 z1 z2 z3 ... zN)
15 The centeroids should be set to origin prior to
16 computing the rotation matrix.
18 The rotation matrix is computed using quaternion
19 algebra as detailed in::
21 Melander et al. J. Chem. Theory Comput., 2015, 11,1055
22 """
24 v0 = np.copy(m0)
25 v1 = np.copy(m1)
27 # compute the rotation quaternion
29 R11, R22, R33 = np.sum(v0 * v1, axis=1)
30 R12, R23, R31 = np.sum(v0 * np.roll(v1, -1, axis=0), axis=1)
31 R13, R21, R32 = np.sum(v0 * np.roll(v1, -2, axis=0), axis=1)
33 f = [[R11 + R22 + R33, R23 - R32, R31 - R13, R12 - R21],
34 [R23 - R32, R11 - R22 - R33, R12 + R21, R13 + R31],
35 [R31 - R13, R12 + R21, -R11 + R22 - R33, R23 + R32],
36 [R12 - R21, R13 + R31, R23 + R32, -R11 - R22 + R33]]
38 F = np.array(f)
40 w, V = np.linalg.eigh(F)
41 # eigenvector corresponding to the most
42 # positive eigenvalue
43 q = V[:, np.argmax(w)]
45 # Rotation matrix from the quaternion q
47 R = quaternion_to_matrix(q)
49 return R
52def quaternion_to_matrix(q):
53 """Returns a rotation matrix.
55 Computed from a unit quaternion Input as (4,) numpy array.
56 """
58 q0, q1, q2, q3 = q
59 R_q = [[q0**2 + q1**2 - q2**2 - q3**2,
60 2 * (q1 * q2 - q0 * q3),
61 2 * (q1 * q3 + q0 * q2)],
62 [2 * (q1 * q2 + q0 * q3),
63 q0**2 - q1**2 + q2**2 - q3**2,
64 2 * (q2 * q3 - q0 * q1)],
65 [2 * (q1 * q3 - q0 * q2),
66 2 * (q2 * q3 + q0 * q1),
67 q0**2 - q1**2 - q2**2 + q3**2]]
68 return np.array(R_q)
71def minimize_rotation_and_translation(target, atoms):
72 """Minimize RMSD between atoms and target.
74 Rotate and translate atoms to best match target. For more details, see::
76 Melander et al. J. Chem. Theory Comput., 2015, 11,1055
77 """
79 p = atoms.get_positions()
80 p0 = target.get_positions()
82 # centeroids to origin
83 c = np.mean(p, axis=0)
84 p -= c
85 c0 = np.mean(p0, axis=0)
86 p0 -= c0
88 # Compute rotation matrix
89 R = rotation_matrix_from_points(p.T, p0.T)
91 atoms.set_positions(np.dot(p, R.T) + c0)