def test_analytical(self): """ Test analytical calculation of the upper bound using SVD and eigenvalue decomposition. """ tol = 1e-10 n = int(1e3) X, Y = load_coords(['1ake', '4ake']) A = np.dot(X.T, Y) R = fit(X, Y)[0] func = spin.NearestRotation(A) func2 = spin.NearestUnitQuaternion(A) self.assertTrue(spin.distance(func.optimum(), R) < tol) self.assertTrue(np.linalg.norm(func2.optimum().dofs-spin.Quaternion(R).dofs) < tol) rotations = spin.random_rotation(n) vals = np.array(list(map(func, rotations))) vals2 = np.dot(rotations.reshape(n,-1), A.flatten()) self.assertTrue(np.fabs(vals-vals2).max() < tol) self.assertTrue(np.all(vals <= func(func.optimum().matrix))) self.assertTrue(np.all(vals <= func2(func2.optimum())))
def setUp(self): self.coords = coords = load_coords(['1ake', '4ake']) self.lsq = dict(svd=spin.LeastSquares(*coords), euler=spin.LeastSquares(*coords, trafo=spin.EulerAngles()), expmap=spin.LeastSquares(*coords, trafo=spin.ExponentialMap()), axisangle=spin.LeastSquares(*coords, trafo=spin.AxisAngle()), quaternion=spin.LeastSquares(*coords, trafo=spin.Quaternion()))
def setUp(self): rot_types = (spin.Rotation, spin.EulerAngles, spin.ExponentialMap, spin.AxisAngle, spin.Quaternion) R = spin.random_rotation() t = np.random.standard_normal(3) * 10 trafos = [ spin.RigidTransformation(R, t, rot_type) for rot_type in rot_types ] self.coords = load_coords(['1ake', '4ake']) self.trafos = trafos
def test_opt(self): """ Constrained optimization to determine the best unit quaternion """ coords = load_coords(['1ake', '4ake']) A = np.dot(coords[0].T,coords[1]) R = fit(*coords)[0] func = spin.NearestUnitQuaternion(A) q_opt = func.optimum().dofs q_opt2 = spin.NearestRotation(A, spin.Quaternion()).optimum().dofs ## constrained optimization constraint = [{'type': 'eq', 'fun': lambda q : np.dot(q,q) - 1}] best = -1e308, None for n_trials in range(10): q_start = spin.Quaternion.random() result = opt.minimize(lambda q: -func(q), q_start, constraints=constraint) q_best = result['x'] * np.sign(result['x'][0]) if abs(constraint[0]['fun'](q_best)) < 1e-10 and func(q_best) > best[0]: best = func(q_best), q_best _, q_best = best print(make_title('finding nearest rotation matrix / unit quaternion')) print(np.round(q_opt, 5)) print(np.round(q_best, 5)) print(np.round(q_opt2, 5)) tol = 1e-5 self.assertTrue(np.linalg.norm(q_opt - q_best) < tol) self.assertTrue(np.linalg.norm(q_opt - q_opt2) < tol)
""" Compare least-squares fitting with unit quaternions (Kearsley's algorithm) with fitting using singular value decomposition (Kabsch's algorithm). """ from __future__ import print_function import spin import time import numpy as np from littlehelpers import load_coords from csb.bio.utils import fit X, Y = load_coords(['1ake', '4ake']) n = 1000 X = np.repeat(X, n, axis=0) Y = np.repeat(Y, n, axis=0) t = time.clock() A = spin.qfit(X, Y) t = time.clock() - t t2 = time.clock() B = fit(X, Y) t2 = time.clock() - t2 print('dist(R_quat,R_svd) = {0:.3f}'.format(spin.distance(A[0], B[0]))) print('dist(t_quat,t_svd) = {0:.3f}'.format(np.linalg.norm(A[1] - B[1]))) print('times: {0:.3f} vs {1:.3f} (quat vs svd)'.format(t, t2))