1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """Module for handling all types of structural statistics."""
24
25
26 from numpy import array, float64, mean, ones, sqrt, std, zeros
27 from numpy.linalg import norm
28
29
31 """Determine the RMSD for the given atomic coordinates.
32
33 This is the per atom RMSD to the mean structure.
34
35
36 @keyword coord: The array of molecular coordinates. The first dimension corresponds to the model, the second the atom, the third the coordinate.
37 @type coord: rank-3 numpy array
38 @return: The RMSD value.
39 @rtype: float
40 """
41
42
43 M = len(coord)
44 N = len(coord[0])
45 model_rmsd = zeros(M, float64)
46 mean_str = zeros((N, 3), float64)
47
48
49 calc_mean_structure(coord, mean_str)
50
51
52 for i in range(M):
53
54 for j in range(N):
55
56 vect = mean_str[j] - coord[i][j]
57
58
59 model_rmsd[i] += norm(vect)**2
60
61
62 model_rmsd[i] = sqrt(model_rmsd[i] / N)
63
64
65 if verbosity:
66 print("Model %2s RMSD: %s" % (i, model_rmsd[i]))
67
68
69 rmsd_mean = sqrt(mean(model_rmsd**2))
70
71
72 try:
73 rmsd_sd = sqrt(std(model_rmsd**2, ddof=1))
74
75
76 except TypeError:
77 rmsd_sd = sqrt(std(model_rmsd**2) * sqrt(M / (M - 1.0)))
78
79
80 if verbosity:
81 print("\nGlobal RMSD: %s +/- %s" % (rmsd_mean, rmsd_sd))
82
83
84 return rmsd_mean
85
86
88 """Average the coordinates.
89
90 @keyword coord: The list of coordinates of all models to superimpose. The first index is the models, the second is the atomic positions, and the third is the xyz coordinates.
91 @type coord: list of numpy rank-2, Nx3 arrays
92 @keyword weights: The weights for each structure.
93 @type weights: list of float
94 @keyword mean: The data storage for the mean structure.
95 @type mean: numpy rank-2, Nx3 array
96 """
97
98
99 N = len(coord[0])
100 M = len(coord)
101 if weights is None:
102 weights = ones(M, float64)
103 else:
104 weights = array(weights, float64)
105
106
107 for i in range(N):
108 mean[i] = [0.0, 0.0, 0.0]
109
110
111 for i in range(N):
112
113 for j in range(M):
114 mean[i] += weights[j] * coord[j][i]
115
116
117 mean[i] = mean[i] / weights.sum()
118
119
121 """Determine the per-atom RMSDs for the given atomic coordinates.
122
123 This is the per atom RMSD to the mean structure.
124
125
126 @keyword coord: The array of molecular coordinates. The first dimension corresponds to the model, the second the atom, the third the coordinate.
127 @type coord: rank-3 numpy array
128 @return: The list of RMSD values for each atom.
129 @rtype: rank-1 numpy float64 array
130 """
131
132
133 M = len(coord)
134 N = len(coord[0])
135 model_rmsd = zeros(M, float64)
136 mean_str = zeros((N, 3), float64)
137 rmsd = zeros(N, float64)
138
139
140 calc_mean_structure(coord, mean_str)
141
142
143 for j in range(N):
144
145 for i in range(M):
146
147 vect = mean_str[j] - coord[i][j]
148
149
150 rmsd[j] += norm(vect)**2
151
152
153 rmsd[j] = sqrt(rmsd[j] / M)
154
155
156 return rmsd
157