예제 #1
0
    def test_efg(self):

        eth = io.read(os.path.join(_TESTDATA_DIR, 'ethanol.magres'))

        # Load the data calculated with MagresView
        with open(os.path.join(_TESTDATA_DIR, 'ethanol_efg.dat')) as f:
            data = f.readlines()[8:]

        asymm = EFGAsymmetry.get(eth)

        qprop = EFGQuadrupolarConstant(isotopes={'H': 2})
        qcnst = qprop(eth)
        quats = EFGQuaternion.get(eth)

        for i, d in enumerate(data):
            vals = [float(x) for x in d.split()[1:]]
            if len(vals) != 8:
                continue
            # And check...
            # The quadrupolar constant has some imprecision due to values
            # of quadrupole moment, so we only ask 2 places in kHz
            self.assertAlmostEqual(qcnst[i] * 1e-3, vals[0] * 1e-3, places=2)
            self.assertAlmostEqual(asymm[i], vals[1])
            vq = Quaternion.from_euler_angles(*(np.array(vals[-3:]) * np.pi /
                                                180.0))
            # Product to see if they go back to the origin
            # The datafile contains conjugate quaternions
            pq = vq * quats[i]
            cosphi = np.clip(pq.q[0], -1, 1)
            phi = np.arccos(cosphi)
            # 180 degrees rotations are possible (signs are not fixed)
            self.assertTrue(
                np.isclose((phi * 2) % np.pi, 0) or np.isclose(
                    (phi * 2) % np.pi, np.pi))
예제 #2
0
def test_quaternions_euler(rng):

    # Fourth: test Euler angles
    for mode in ['zyz', 'zxz']:
        for i in range(TEST_N):

            abc = rng.rand(3) * 2 * np.pi

            q_eul = Quaternion.from_euler_angles(*abc, mode=mode)
            rot_eul = eulang_rotm(*abc, mode=mode)

            assert(np.allclose(rot_eul, q_eul.rotation_matrix()))

            # Test conversion back and forth
            abc_2 = q_eul.euler_angles(mode=mode)
            q_eul_2 = Quaternion.from_euler_angles(*abc_2, mode=mode)

            assert(np.allclose(q_eul_2.q, q_eul.q))
예제 #3
0
def test_quaternions_euler(rng):

    # Fourth: test Euler angles
    for mode in ['zyz', 'zxz']:
        for i in range(TEST_N):

            abc = rng.rand(3) * 2 * np.pi
            v2 = rng.rand(2, 3)  # Two random vectors to rotate rigidly

            q_eul = Quaternion.from_euler_angles(*abc, mode=mode)
            rot_eul = eulang_rotm(*abc, mode=mode)

            v2_q = np.array([q_eul.rotate(v) for v in v2])
            v2_m = np.array([np.dot(rot_eul, v) for v in v2])

            assert np.allclose(v2_q, v2_m)
예제 #4
0
    # Now test this with a vector
    v = rndstate.rand(3)

    vrotM = np.dot(rotm2, np.dot(rotm1, v))
    vrotQ = (q2 * q1).rotate(v)

    assert np.allclose(vrotM, vrotQ)

# Fourth: test Euler angles
for mode in ['zyz', 'zxz']:
    for i in range(test_n):

        abc = rndstate.rand(3)*2*np.pi
        v2 = rndstate.rand(2, 3)  # Two random vectors to rotate rigidly

        q_eul = Quaternion.from_euler_angles(*abc, mode=mode)
        rot_eul = eulang_rotm(*abc, mode=mode)

        v2_q = np.array([q_eul.rotate(v) for v in v2])
        v2_m = np.array([np.dot(rot_eul, v) for v in v2])

        assert np.allclose(v2_q, v2_m)

# Fifth: test that conversion back to rotation matrices works properly
for i in range(test_n):

    rotm1 = rand_rotm(rndstate)
    rotm2 = rand_rotm(rndstate)

    q1 = Quaternion.from_matrix(rotm1)
    q2 = Quaternion.from_matrix(rotm2)
예제 #5
0
def test_quaternions():
    import numpy as np
    from ase.quaternions import Quaternion

    def axang_rotm(u, theta):

        u = np.array(u, float)
        u /= np.linalg.norm(u)

        # Cross product matrix for u
        ucpm = np.array([[0, -u[2], u[1]], [u[2], 0, -u[0]], [-u[1], u[0], 0]])

        # Rotation matrix
        rotm = (np.cos(theta) * np.identity(3) + np.sin(theta) * ucpm +
                (1 - np.cos(theta)) * np.kron(u[:, None], u[None, :]))

        return rotm

    def rand_rotm(rndstate=np.random.RandomState(0)):
        """Axis & angle rotations."""
        u = rndstate.rand(3)
        theta = rndstate.rand() * np.pi * 2

        return axang_rotm(u, theta)

    def eulang_rotm(a, b, c, mode='zyz'):

        rota = axang_rotm([0, 0, 1], a)
        rotc = axang_rotm([0, 0, 1], c)

        if mode == 'zyz':
            rotb = axang_rotm([0, 1, 0], b)
        elif mode == 'zxz':
            rotb = axang_rotm([1, 0, 0], b)

        return np.dot(rotc, np.dot(rotb, rota))

    # Random state for testing
    rndstate = np.random.RandomState(0)
    test_n = 200

    # First: test that rotations DO work
    for i in range(test_n):
        # n random tests

        rotm = rand_rotm(rndstate)

        q = Quaternion.from_matrix(rotm)

        # Now test this with a vector
        v = rndstate.rand(3)

        vrotM = np.dot(rotm, v)
        vrotQ = q.rotate(v)

        assert np.allclose(vrotM, vrotQ)

    # Second: test the special case of a PI rotation

    rotm = np.identity(3)
    rotm[:2, :2] *= -1  # Rotate PI around z axis

    q = Quaternion.from_matrix(rotm)

    assert not np.isnan(q.q).any()

    # Third: test compound rotations and operator overload
    for i in range(test_n):

        rotm1 = rand_rotm(rndstate)
        rotm2 = rand_rotm(rndstate)

        q1 = Quaternion.from_matrix(rotm1)
        q2 = Quaternion.from_matrix(rotm2)

        # Now test this with a vector
        v = rndstate.rand(3)

        vrotM = np.dot(rotm2, np.dot(rotm1, v))
        vrotQ = (q2 * q1).rotate(v)

        assert np.allclose(vrotM, vrotQ)

    # Fourth: test Euler angles
    for mode in ['zyz', 'zxz']:
        for i in range(test_n):

            abc = rndstate.rand(3) * 2 * np.pi
            v2 = rndstate.rand(2, 3)  # Two random vectors to rotate rigidly

            q_eul = Quaternion.from_euler_angles(*abc, mode=mode)
            rot_eul = eulang_rotm(*abc, mode=mode)

            v2_q = np.array([q_eul.rotate(v) for v in v2])
            v2_m = np.array([np.dot(rot_eul, v) for v in v2])

            assert np.allclose(v2_q, v2_m)

    # Fifth: test that conversion back to rotation matrices works properly
    for i in range(test_n):

        rotm1 = rand_rotm(rndstate)
        rotm2 = rand_rotm(rndstate)

        q1 = Quaternion.from_matrix(rotm1)
        q2 = Quaternion.from_matrix(rotm2)

        assert (np.allclose(q1.rotation_matrix(), rotm1))
        assert (np.allclose(q2.rotation_matrix(), rotm2))
        assert (np.allclose((q1 * q2).rotation_matrix(), np.dot(rotm1, rotm2)))