예제 #1
0
    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())))
예제 #2
0
    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()))
예제 #3
0
    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
예제 #4
0
    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)
예제 #5
0
"""
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))