1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """
24 superimpose 2 structures iteratively
25 """
26
27 import Biskit.mathUtils as MU
28 import Numeric as N
29 from LinearAlgebra import singular_value_decomposition as svd
30
31
32
33
34
35
36
37
38
39
40
69
70
71 -def match(x, y, n_iterations=1, z=2, eps_rmsd=0.5, eps_stdv=0.05):
72 """
73 Matches two arrays onto each other, while iteratively removing outliers.
74 Superimposed array y would be C{ N.dot(y, N.transpose(r)) + t }.
75
76 @param n_iterations: number of calculations::
77 1 .. no iteration
78 0 .. until convergence
79 @type n_iterations: 1|0
80 @param z: number of standard deviations for outlier definition (default: 2)
81 @type z: float
82 @param eps_rmsd: tolerance in rmsd (default: 0.5)
83 @type eps_rmsd: float
84 @param eps_stdv: tolerance in standard deviations (default: 0.05)
85 @type eps_stdv: float
86
87 @return: (r,t), [ [percent_considered, rmsd_for_it, outliers] ]
88 @rtype: (array, array), [float, float, int]
89 """
90 iter_trace = []
91
92 rmsd_old = 0
93 stdv_old = 0
94
95 n = 0
96 converged = 0
97
98 mask = N.ones(len(y))
99
100 while not converged:
101
102
103 r, t = findTransformation(N.compress(mask, x, 0),
104 N.compress(mask, y, 0))
105
106
107 xt = N.dot(y, N.transpose(r)) + t
108
109
110 d = N.sqrt(N.sum(N.power(x - xt, 2), 1)) * mask
111
112
113 rmsd = N.sqrt(N.average(N.compress(mask, d)**2))
114 stdv = MU.SD(N.compress(mask, d))
115
116
117 d_rmsd = abs(rmsd - rmsd_old)
118 d_stdv = abs(1 - stdv_old / stdv)
119
120 if d_rmsd < eps_rmsd and d_stdv < eps_stdv:
121 converged = 1
122 else:
123 rmsd_old = rmsd
124 stdv_old = stdv
125
126
127 perc = round(float(N.sum(mask)) / float(len(mask)), 2)
128
129
130 mask = N.logical_and(mask, N.less(d, rmsd + z * stdv))
131 outliers = N.nonzero( N.logical_not( mask ) )
132 iter_trace.append([perc, round(rmsd, 3), outliers])
133
134 n += 1
135
136 if n_iterations and n >= n_iterations:
137 break
138
139 return (r, t), iter_trace
140
141
143 """
144 Calculate the distances between the items of two arrays (of same shape)
145 after least-squares superpositioning.
146
147 @param x: first set of coordinates
148 @type x: array('f')
149 @param y: second set of coordinates
150 @type y: array('f')
151
152 @return: array( len(x), 'f' ), distance between x[i] and y[i] for all i
153 @rtype: array
154 """
155
156 r, t = findTransformation(x, y)
157
158
159 z = N.dot(y, N.transpose(r)) + t
160
161
162 return N.sqrt(N.sum(N.power(x - z, 2), 1))
163
164
165
166
167
168
169
171 """
172 Test class
173 """
174
175
176 - def run( self, local=0 ):
177 """
178 run function test
179
180 @param local: transfer local variables to global and perform
181 other tasks only when run locally
182 @type local: 1|0
183
184 @return: rotation matrix
185 @rtype: array
186 """
187 import Biskit.tools as T
188
189 traj = T.Load( T.testRoot() + '/lig_pcr_00/traj.dat' )
190
191 rt, rmsdLst = match( traj.ref.xyz, traj[-1].xyz)
192
193 if local:
194 print 'RMSD: %.2f'%rmsdLst[0][1]
195 globals().update( locals() )
196
197
198 return rt[0]
199
200
202 """
203 Precalculated result to check for consistent performance.
204
205 @return: rotation matrix
206 @rtype: array
207 """
208 return N.array( [[ 0.9999011, 0.01311352, 0.00508244,],
209 [-0.01310219, 0.99991162, -0.00225578,],
210 [-0.00511157, 0.00218896, 0.99998454 ]] )
211
212
213 if __name__ == '__main__':
214
215 test = Test()
216
217 assert abs( N.sum( N.ravel( test.run( local=1 )- test.expected_result() ) ) ) < 1e-6
218