Beispiel #1
0
    def test_matrix(self):

        dofs = spin.ExponentialMap.random()
        rot = spin.ExponentialMap(dofs)
        rot2 = spin.ExponentialMap.from_rotation(rot)
        rot3 = ExponentialMap(dofs)

        print(make_title('Cython (from dofs)'))
        print(rot)

        print(make_title('Cython (from matrix)'))
        print(rot2)

        print(make_title('Python (from dofs)'))
        print(rot3)

        axis, angle = rot.axis_angle
        r, theta, phi = csb.polar3d(axis)
        axisangle = spin.AxisAngle([theta, phi, angle])
        rot4 = spin.Rotation(csb.rotation_matrix(axis, -angle))

        self.assertTrue(spin.distance(rot, rot2) < self.tol)
        self.assertTrue(spin.distance(rot, rot4) < self.tol)
        self.assertTrue(spin.distance(rot3, rot4) < self.tol)
        self.assertTrue(spin.distance(rot2, axisangle) < self.tol)
Beispiel #2
0
    def test_gradients(self):

        print(make_title('testing gradients'))

        A = np.random.standard_normal((3,3))

        func = [spin.NearestRotation(A, trafo=rot()) for rot in \
                (spin.EulerAngles, spin.ExponentialMap,
                 spin.AxisAngle, spin.Quaternion)]
        func+= [spin.NearestUnitQuaternion(A), spin.NearestQuaternion(A)]

        out   = '{0:>14}: err={1:.3e}, cc={2:.2f}'
        grads = []
        
        for f in func:

            x = f.trafo.dofs
            a = f.gradient(x)
            b = opt.approx_fprime(x, f, 1e-7)

            err, cc = compare_grad(a,b)

            print(out.format(f.trafo.name, err, cc))

            self.assertAlmostEqual(err, 0., delta=1e-5)
            self.assertAlmostEqual(cc, 100., delta=1e-2)

            grads.append(a)
Beispiel #3
0
    def test_gradients2(self):
        """
        Compare gradients of both implementations using quaternions
        """
        print(make_title('gradient of quaternion-based implementations'))
        
        out   = '{0:>20}: err={1:.3e}, cc={2:.2f}'

        A = np.random.standard_normal((3,3))
        f = spin.NearestRotation(A, trafo=spin.Quaternion())
        g = spin.NearestQuaternion(A)
        h = spin.NearestUnitQuaternion(A)
        
        q = f.trafo.random() if False else np.random.standard_normal(4)
        a = f.gradient(q)
        b = g.gradient(q)
        c = h.gradient(q)
        
        print('f(q)={0:.2e}, g(q)={1:.2e}, h(q)={3:.2e}, norm={2:.2e}'.format(
            f(q), g(q), np.dot(q,q), h(q)))
        print(np.corrcoef(a,b)[0,1])

        print('{0:>22}: {1}'.format(f.__class__.__name__, np.round(a,3)))
        print('{0:>22}: {1}'.format(g.__class__.__name__, np.round(b,3)))
        print('{0:>22}: {1}'.format(h.__class__.__name__, np.round(c,3)))
        
        self.assertAlmostEqual(np.linalg.norm(a-b), 0., delta=1e-5)
Beispiel #4
0
    def test_lsq(self):

        rotation, score = self.lsq['svd'].optimum()

        rmsd_ = [
            np.sqrt(score / len(self.coords[0])),
            self.lsq['svd'].rmsd(rotation.matrix),
            rmsd(*self.coords)
        ]
        lsq_ = [0.5 * score, self.lsq['svd'](rotation.matrix)]

        for name in ('euler', 'axisangle', 'expmap', 'axisangle'):

            dofs = self.lsq[name].trafo.from_rotation(rotation).dofs
            lsq_.append(self.lsq[name](dofs))

        rmsd_ = np.round(rmsd_, 5)
        lsq_ = np.round(lsq_, 2)

        print(make_title('checking LSQ optimization using SVD'))
        print('RMSD: {0}'.format(rmsd_))
        print(' LSQ: {0}'.format(lsq_))

        tol = 1e-10

        self.assertTrue(np.all(np.fabs(rmsd_ - rmsd_[0]) < tol))
        self.assertTrue(np.all(np.fabs(lsq_ - lsq_[0]) < tol))
        self.assertAlmostEqual(spin.distance(
            fit(*self.coords)[0], rotation.matrix),
                               0.,
                               delta=tol)
Beispiel #5
0
    def test_angles(self):

        print(make_title('angular distributions'))

        n = int(1e5)
        nbins = n // 100
        tol = 1e-2

        kw_hist = dict(bins=nbins)
        if sys.version_info[0] == 2:
            kw_hist['normed'] = True
        else:
            kw_hist['density'] = True

        for angle in (spin.Azimuth, spin.Polar, spin.RotationAngle):

            x = angle.random(n)
            p, bins = np.histogram(x, **kw_hist)
            q = angle.prob(0.5 * (bins[1:] + bins[:-1]))

            mse = np.mean((q - p)**2)

            print('{0:>15}: MSE={1:.3e}'.format(angle.__name__, mse))

            min_, max_ = angle.axis(2)

            self.assertTrue(mse < tol)
            self.assertTrue(min_ <= np.min(x))
            self.assertTrue(max_ >= np.max(x))
Beispiel #6
0
    def test_opt(self):

        print(make_title('test optimization of least-squares residual'))

        out = '{0:>14}: #steps={1:3d}, RMSD: {5:.2f}->{2:.2f}, ' + \
              'accuracy: {3:.3e} (rot), {4:.3e} (trans)'

        start = spin.random_rotation(), np.random.standard_normal(3) * 10
        R, t = fit(*self.coords)

        rot = []
        trans = []
        rmsds = []

        for trafo in self.trafos[1:]:

            trafo.matrix_vector = start

            f = spin.LeastSquares(*self.coords, trafo=trafo)
            x = trafo.dofs.copy()
            y = opt.fmin_bfgs(f, x, f.gradient, disp=False)

            rot.append(spin.distance(R, trafo.rotation))
            trans.append(np.linalg.norm(t - trafo.translation.vector))
            rmsds.append(np.sqrt(2 * f(y) / len(self.coords[0])))

            print(
                out.format(trafo.rotation.name, len(f.values), rmsds[-1],
                           rot[-1], trans[-1],
                           np.sqrt(2 * f(x) / len(self.coords[0]))))

            self.assertAlmostEqual(rot[-1], 0., delta=1e-5)
            self.assertAlmostEqual(trans[-1], 0., delta=1e-5)

        self.assertAlmostEqual(np.std(rmsds), 0., delta=1e-5)
Beispiel #7
0
    def test_optimizers(self):
        """
        Test various optimizers for finding the optimal rotation
        in Euler parameterization
        """
        optimizers = OrderedDict()
        optimizers['nedler-mead'] = opt.fmin
        optimizers['powell'] = opt.fmin_powell
        optimizers['bfgs'] = opt.fmin_bfgs

        print(make_title('Testing different optimizers'))

        rotation, _ = self.lsq['svd'].optimum()
        lsq_opt = self.lsq['svd'](rotation.matrix)
        output = '{0:11s} : min.score={1:.2f}, dist={2:.3e}, nsteps={3:d}'

        for name, lsq in self.lsq.items():

            if name == 'svd': continue

            print(make_title(lsq.trafo.name))

            start = lsq.trafo.random()

            results = OrderedDict()

            for method, run in optimizers.items():

                lsq.values = []

                args = [lsq, start.copy()
                        ] + ([lsq.gradient] if method == 'bfgs' else [])
                best = run(*args, disp=False)

                results[method] = np.array(lsq.values)

                summary = lsq(best), spin.distance(rotation,
                                                   lsq.trafo), len(lsq.values)

                print(output.format(*((method, ) + summary)))

            fig, ax = plt.subplots(1, 1, figsize=(10, 6))
            fig.suptitle(lsq.trafo.name)
            for method, values in results.items():
                ax.plot(values, lw=5, alpha=0.7, label=method)
            ax.axhline(lsq_opt, lw=3, ls='--', color='r')
            ax.legend()
Beispiel #8
0
    def test_skew_matrix(self):

        a, b = np.random.standard_normal((2, 3))
        A = spin.rotation.skew_matrix(a)

        x = np.dot(A, b)
        y = np.cross(a, b)

        print(make_title('action of skew matrix vs cross product'))
        print('  Skew matrix: {0}'.format(np.round(x, 5)))
        print('Cross product: {0}'.format(np.round(y, 5)))

        for i in range(len(x)):
            self.assertAlmostEqual(x[i], y[i], delta=1e-10)
Beispiel #9
0
    def test_params(self):

        rigid = self.trafos[0]

        print(make_title('comparing matrix and vector'))
        out = '{0:14s} : distance rotation={1:.3e}, translation={2:.3e}'

        for other in self.trafos[1:]:

            dist_rot = spin.distance(rigid.rotation, other.rotation)
            dist_trans = np.linalg.norm(rigid.translation.vector -
                                        other.translation.vector)

            print(out.format(other.rotation.name, dist_rot, dist_trans))

            self.assertAlmostEqual(dist_rot, 0., delta=1e-10)
            self.assertAlmostEqual(dist_trans, 0., delta=1e-10)
Beispiel #10
0
    def test_gradient(self):
        """
        Numerical vs analytical gradient
        """
        print(make_title('Checking gradient'))

        out = '{0:>15}: rel.error={1:.2e}, corr={2:.2f}%'

        for name, lsq in self.lsq.items():

            if name == 'svd': continue

            dofs = lsq.trafo.random()
            grad = lsq.gradient(dofs)
            num = opt.approx_fprime(dofs, lsq, 1e-7)

            err, cc = compare_grad(grad, num)

            print(out.format(lsq.trafo.name, err, cc))

            self.assertAlmostEqual(cc, 100, delta=1e-2)
            self.assertAlmostEqual(err, 0., delta=1e-5)
Beispiel #11
0
    def test_grad(self):

        print(make_title('checking gradient'))

        pose = spin.random_rotation(), np.random.standard_normal(3) * 10
        out = '{0:>14}: corr={1:.1f}, rel.error={2:.3e}'

        for trafo in self.trafos[1:]:

            trafo.matrix_vector = pose

            f = spin.LeastSquares(*self.coords, trafo=trafo)
            x = trafo.dofs.copy()
            a = f.gradient(x)
            b = opt.approx_fprime(x, f, 1e-8)

            err, cc = compare_grad(a, b)

            print(out.format(trafo.rotation.name, cc, err))

            self.assertAlmostEqual(cc, 100., delta=1e-2)
            self.assertAlmostEqual(err, 0., delta=1e-5)
Beispiel #12
0
    def test_rmsd(self):

        R, t = fit(*self.coords)
        out = '{0:.2f} ({1})'

        print(make_title('RMSD'))
        print(out.format(rmsd(*self.coords), 'SVD'))

        rmsds = []

        for trafo in self.trafos[1:]:

            trafo.matrix_vector = R, t

            r = np.mean(np.sum((self.coords[0] - trafo(self.coords[1]))**2,
                               1))**0.5

            print(out.format(r, trafo.rotation.name))

            rmsds.append(r)

        self.assertAlmostEqual(np.std(rmsds), 0., delta=1e-10)
Beispiel #13
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)