Beispiel #1
0
    def test_swing_twist(self):

        from ase.quaternions import Quaternion

        test_n = 10

        for t_i in range(test_n):

            # Create two quaternions with random rotations
            theta1, theta2 = np.random.random(2) * 2 * np.pi
            ax1 = np.random.random(3)
            ax2 = np.cross(np.random.random(3), ax1)
            ax1 /= np.linalg.norm(ax1)
            ax2 /= np.linalg.norm(ax2)

            q1 = Quaternion([np.cos(theta1 / 2)] +
                            list(ax1 * np.sin(theta1 / 2)))
            q2 = Quaternion([np.cos(theta2 / 2)] +
                            list(ax2 * np.sin(theta2 / 2)))

            qT = q1 * q2

            # Now decompose
            qsw, qtw = swing_twist_decomp(qT, ax2)
            # And check
            q1.q *= np.sign(q1.q[0])
            q2.q *= np.sign(q2.q[0])
            qsw.q *= np.sign(qsw.q[0])
            qtw.q *= np.sign(qtw.q[0])

            self.assertTrue(np.allclose(q1.q, qsw.q))
            self.assertTrue(np.allclose(q2.q, qtw.q))
Beispiel #2
0
Datei: view.py Projekt: adbX/ase
    def my_arc(self, gc, fill, j, X, r, n, A, d):

        if self.images.shapes is not None:
            rx = (self.images.shapes[j, 0]).round().astype(int)
            ry = (self.images.shapes[j, 1]).round().astype(int)
            rz = (self.images.shapes[j, 2]).round().astype(int)
            circle = rx == ry and ry == rz

            if not circle:
                Q = Quaternion(self.images.Q[self.frame][j])
                X2d = np.array([X[j][0], X[j][1]])
                Ellipsoid = np.array([[1. / (rx * rx), 0, 0],
                                      [0, 1. / (ry * ry), 0],
                                      [0, 0, 1. / (rz * rz)]])
                # Ellipsoid rotated by quaternion as Matrix X' = R X R_transpose
                El_r = np.dot(
                    Q.rotation_matrix(),
                    np.dot(Ellipsoid, np.transpose(Q.rotation_matrix())))
                # Ellipsoid rotated by quaternion and axes as
                # Matrix X' =  R_axes X' R_axes
                El_v = np.dot(np.transpose(self.axes), np.dot(El_r, self.axes))
                # Projection of rotated ellipsoid on xy plane
                El_p = Ell = np.array(
                    [[
                        El_v[0][0] - El_v[0][2] * El_v[0][2] / El_v[2][2],
                        El_v[0][1] - El_v[0][2] * El_v[1][2] / El_v[2][2]
                    ],
                     [
                         El_v[0][1] - El_v[0][2] * El_v[1][2] / El_v[2][2],
                         El_v[1][1] - El_v[1][2] * El_v[1][2] / El_v[2][2]
                     ]])
                # diagonal matrix der Ellipse gibt halbachsen
                El_p_diag = np.linalg.eig(El_p)
                # Winkel mit dem Ellipse in xy gedreht ist aus
                # eigenvektor der diagonal matrix
                phi = atan(El_p_diag[1][0][1] / El_p_diag[1][0][0])
                tupl = []
                alpha = np.array(range(16)) * 2 * np.pi / 16
                El_xy = np.array([
                    sqrt(1. /
                         (El_p_diag[0][0])) * np.cos(alpha) * np.cos(phi) -
                    sqrt(1. / (El_p_diag[0][1])) * np.sin(alpha) * np.sin(phi),
                    sqrt(1. /
                         (El_p_diag[0][0])) * np.cos(alpha) * np.sin(phi) +
                    sqrt(1. / (El_p_diag[0][1])) * np.sin(alpha) * np.cos(phi)
                ])

                tupl = (El_xy.transpose() * self.scale +
                        X[j][:2]).round().astype(int)
                # XXX there must be a better way
                tupl = [tuple(i) for i in tupl]

                return self.pixmap.draw_polygon(gc, fill, tupl)
            else:
                return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], d[j],
                                            d[j], 0, 23040)
        else:
            return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], d[j], d[j],
                                        0, 23040)
Beispiel #3
0
Datei: view.py Projekt: askhl/ase
    def my_arc(self, gc, fill, j, X, r, n, A, d):
   
        if self.images.shapes is not None:
            rx = (self.images.shapes[j, 0]).round().astype(int)
            ry = (self.images.shapes[j, 1]).round().astype(int)
            rz = (self.images.shapes[j, 2]).round().astype(int)
            circle = rx == ry and ry == rz

            if not circle:
                Q = Quaternion(self.images.Q[self.frame][j])
                X2d = np.array([X[j][0], X[j][1]])
                Ellipsoid = np.array([[1. / (rx*rx), 0, 0],
                                      [0, 1. / (ry*ry), 0],
                                      [0, 0, 1. / (rz*rz)]
                                      ])
                # Ellipsoid rotated by quaternion as Matrix X' = R X R_transpose
                El_r = np.dot(Q.rotation_matrix(),
                              np.dot(Ellipsoid, 
                                     np.transpose(Q.rotation_matrix())))
                # Ellipsoid rotated by quaternion and axes as 
                # Matrix X' =  R_axes X' R_axes
                El_v = np.dot(np.transpose(self.axes), np.dot(El_r, self.axes))
                # Projection of rotated ellipsoid on xy plane
                El_p = Ell = np.array([
                        [El_v[0][0] - El_v[0][2] * El_v[0][2] / El_v[2][2],
                         El_v[0][1] - El_v[0][2] * El_v[1][2] / El_v[2][2]],
                        [El_v[0][1] - El_v[0][2] * El_v[1][2] / El_v[2][2],
                         El_v[1][1] - El_v[1][2] * El_v[1][2] / El_v[2][2]]
                        ])
                # diagonal matrix der Ellipse gibt halbachsen
                El_p_diag = np.linalg.eig(El_p)
                # Winkel mit dem Ellipse in xy gedreht ist aus 
                # eigenvektor der diagonal matrix
                phi = atan(El_p_diag[1][0][1] / El_p_diag[1][0][0])
                tupl = []
                alpha = np.array(range(16)) * 2 * np.pi / 16
                El_xy = np.array([sqrt(1. / (El_p_diag[0][0])) *
                                  np.cos(alpha)*np.cos(phi) 
                                  - sqrt(1./(El_p_diag[0][1])) * 
                                  np.sin(alpha) * np.sin(phi),
                                  sqrt(1./(El_p_diag[0][0])) * 
                                  np.cos(alpha)*np.sin(phi)
                                  + sqrt(1./(El_p_diag[0][1])) * 
                                  np.sin(alpha) * np.cos(phi)])

                tupl = (El_xy.transpose() * self.scale + 
                        X[j][:2]).round().astype(int)
                # XXX there must be a better way
                tupl = [tuple(i) for i in tupl]

                return self.pixmap.draw_polygon( gc, fill, tupl)
            else:
                return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], d[j],
                                            d[j], 0, 23040)
        else:
            return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], d[j], d[j], 
                                        0, 23040)
Beispiel #4
0
    def extract(s, force_recalc):

        if Molecules.default_name not in s.info or force_recalc:
            Molecules.get(s)

        mol_quat = []
        all_m = s.get_masses()
        all_pos = s.get_positions()

        for mol in s.info[Molecules.default_name]:

            mol_pos = all_pos[mol.indices]
            mol_pos += np.tensordot(mol.get_array('cell_indices'),
                                    s.get_cell(),
                                    axes=(1, 1))
            mol_ms = all_m[mol.indices]

            # We still need to correct the positions with the COM
            mol_com = np.sum(mol_pos * mol_ms[:, None],
                             axis=0) / np.sum(mol_ms)
            mol_pos -= mol_com

            tens_i = np.identity(3)[None, :, :] * \
                np.linalg.norm(mol_pos, axis=1)[:, None, None]**2

            tens_i -= mol_pos[:, None, :] * mol_pos[:, :, None]
            tens_i *= mol_ms[:, None, None]
            tens_i = np.sum(tens_i, axis=0)

            evals, evecs = np.linalg.eigh(tens_i)
            # General ordering convention: we want the component of the
            # longest position to be positive along evecs_0, and the component
            # of the second longest (and non-parallel) position to be positive
            # along evecs_1, and the triple to be right-handed of course.
            mol_pos = sorted(mol_pos, key=lambda x: -np.linalg.norm(x))
            if len(mol_pos) > 1:
                evecs[0] *= np.sign(np.dot(evecs[0], mol_pos[0]))
            e1dirs = np.where(
                np.linalg.norm(np.cross(mol_pos, mol_pos[0])) > 0)[0]
            if len(e1dirs) > 0:
                evecs[1] *= np.sign(np.dot(evecs[1], mol_pos[e1dirs[0]]))
            evecs[2] *= np.sign(np.dot(evecs[2], np.cross(evecs[0], evecs[1])))
            # Evecs must be proper
            evecs /= np.linalg.det(evecs)

            quat = Quaternion()
            quat = quat.from_matrix(evecs.T)
            mol_quat.append(quat)

        return mol_quat
def rotation(axis, angle):
    """ 
    Generate the rotation matrix 
    given the rotation axis and angle
    """
    norm = n.linalg.norm(axis)
    tol = 2 * n.finfo(n.float).eps
    q = [n.cos(angle / 2)]
    for a in axis:
        q.append(n.sin(angle / 2.0) * a / norm)
    q = Quaternion(q)
    matrix = q.rotation_matrix()
    matrix[abs(matrix) < tol] = 0.0
    return matrix
Beispiel #6
0
def test_quaternions_rotm(rng):

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

        rotm1 = rand_rotm(rng)
        rotm2 = rand_rotm(rng)

        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)))
Beispiel #7
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))
    def test_transformprops(self):

        from ase.quaternions import Quaternion
        from soprano.selection import AtomSelection
        from soprano.properties.transform import (Translate, Rotate, Mirror)

        a = Atoms('CH', positions=[[0, 0, 0], [0.5, 0, 0]])

        sel = AtomSelection.from_element(a, 'C')
        transl = Translate(selection=sel, vector=[0.5, 0, 0])
        rot = Rotate(selection=sel, center=[0.25, 0.0, 0.25],
                     quaternion=Quaternion([np.cos(np.pi/4.0),
                                            0,
                                            np.sin(np.pi/4.0),
                                            0]))
        mirr = Mirror(selection=sel, plane=[1, 0, 0, -0.25])

        aT = transl(a)
        aR = rot(a)
        aM = mirr(a)

        self.assertAlmostEqual(np.linalg.norm(aT.get_positions()[0]),
                               np.linalg.norm(aT.get_positions()[1]))
        self.assertAlmostEqual(np.linalg.norm(aR.get_positions()[0]),
                               np.linalg.norm(aR.get_positions()[1]))
        self.assertAlmostEqual(np.linalg.norm(aM.get_positions()[0]),
                               np.linalg.norm(aM.get_positions()[1]))
Beispiel #9
0
    def test_diprotavg(self):
        # Test dipolar rotational averaging

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

        from ase.quaternions import Quaternion
        from soprano.properties.transform import Rotate
        from soprano.collection import AtomsCollection
        from soprano.collection.generate import transformGen
        from soprano.properties.nmr import DipolarTensor

        N = 30  # Number of averaging steps
        axis = np.array([1.0, 1.0, 0])
        axis /= np.linalg.norm(axis)

        rot = Rotate(quaternion=Quaternion.from_axis_angle(
            axis, 2*np.pi/N))

        rot_eth = AtomsCollection(transformGen(eth, rot, N))

        rot_dip = [D[(0, 1)]
                   for D in DipolarTensor.get(rot_eth, sel_i=[0], sel_j=[1])]

        dip_avg_num = np.average(rot_dip, axis=0)

        dip_tens = NMRTensor.make_dipolar(eth, 0, 1, rotation_axis=axis)
        dip_avg_tens = dip_tens.data

        self.assertTrue(np.allclose(dip_avg_num, dip_avg_tens))

        # Test eigenvectors
        evecs = dip_tens.eigenvectors
        self.assertTrue(np.allclose(np.dot(evecs.T, evecs), np.eye(3)))
Beispiel #10
0
    def extract(s, selection, center, quaternion, scaled):

        center = np.array(center)
        if center.shape != (3,):
            raise ValueError('Invalid center passed to Rotate.')

        if quaternion is None:
            quaternion = Quaternion()

        sT = s.copy()

        if not scaled:
            pos = sT.get_positions()
        else:
            pos = sT.get_scaled_positions()

        pos -= center
        pos[selection.indices] = quaternion \
            .rotate(pos[selection.indices].T).T
        pos += center

        if not scaled:
            sT.set_positions(pos)
        else:
            sT.set_scaled_positions(pos)

        return sT
Beispiel #11
0
    def draw_axes(self):
        from ase.quaternions import Quaternion
        q = Quaternion().from_matrix(self.axes)
        axes_labels = [
            "<span foreground=\"red\" weight=\"bold\">X</span>",
            "<span foreground=\"green\" weight=\"bold\">Y</span>",
            "<span foreground=\"blue\" weight=\"bold\">Z</span>"
        ]
        axes_length = 15

        for i in self.axes[:, 2].argsort():
            a = 20
            b = self.height - 20
            c = int(self.axes[i][0] * axes_length + a)
            d = int(-self.axes[i][1] * axes_length + b)
            self.pixmap.draw_line(self.foreground_gc, a, b, c, d)

            # The axes label
            layout = self.drawing_area.create_pango_layout(axes_labels[i])
            layout.set_markup(axes_labels[i])
            lox = int(self.axes[i][0] * 20 + 20\
                    - layout.get_size()[0] / 2. / pango.SCALE)
            loy = int(self.height - 20 - self.axes[i][1] * 20\
                    - layout.get_size()[1] / 2. / pango.SCALE)
            self.pixmap.draw_layout(self.foreground_gc, lox, loy, layout)
def test_quaternions_axang(rng):

    # Sixth: test conversion to axis + angle
    q = Quaternion()
    n, theta = q.axis_angle()
    assert(theta == 0)

    u = np.array([1, 0.5, 1])
    u /= np.linalg.norm(u)
    alpha = 1.25

    q = Quaternion.from_matrix(axang_rotm(u, alpha))
    n, theta = q.axis_angle()

    assert(np.isclose(theta, alpha))
    assert(np.allclose(u, n))
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))
Beispiel #14
0
def _evecs_2_quat(evecs):
    """Convert a set of eigenvectors to a Quaternion expressing the
    rotation of the tensor's PAS with respect to the Cartesian axes"""

    # First, guarantee that the eigenvectors express *proper* rotations
    evecs = np.array(evecs) * np.linalg.det(evecs)[:, None, None]

    # Then get the quaternions
    return [Quaternion.from_matrix(evs.T) for evs in evecs]
Beispiel #15
0
def test_quaternions_overload(rng):

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

        rotm1 = rand_rotm(rng)
        rotm2 = rand_rotm(rng)

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

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

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

        assert np.allclose(vrotM, vrotQ)
def test_quaternions_gimbal(rng):

    # 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()
Beispiel #17
0
def swing_twist_decomp(quat, axis):
    """Perform a Swing*Twist decomposition of a Quaternion. This splits the
    quaternion in two: one containing the rotation around axis (Twist), the
    other containing the rotation around a vector parallel to axis (Swing).

    Returns two quaternions: Swing, Twist.
    """

    # Current rotation axis
    ra = quat.q[1:]
    # Ensure that axis is normalised
    axis_norm = axis / np.linalg.norm(axis)
    # Projection of ra along the given axis
    p = np.dot(ra, axis_norm) * axis_norm
    # Create Twist
    qin = [quat.q[0], p[0], p[1], p[2]]
    twist = Quaternion(qin / np.linalg.norm(qin))
    # And Swing
    swing = quat * twist.conjugate()

    return swing, twist
Beispiel #18
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)
Beispiel #19
0
def test_quaternions_rotations(rng):

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

        rotm = rand_rotm(rng)

        q = Quaternion.from_matrix(rotm)

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

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

        assert np.allclose(vrotM, vrotQ)
Beispiel #20
0
 def draw_axes(self):
     from ase.quaternions import Quaternion
     q = Quaternion().from_matrix(self.axes)
     L = np.zeros((10, 2, 3))
     L[:3, 1] = self.axes * 15
     L[3:5] = self.axes[0] * 20
     L[5:7] = self.axes[1] * 20
     L[7:] = self.axes[2] * 20
     L[3:, :, :2] += (((-4, -5), (4, 5)), ((-4, 5), (4, -5)),
                      ((-4, 5), (0, 0)), ((-4, -5), (4, 5)),
                      ((-4, 5), (4, 5)), ((4, 5), (-4, -5)), ((-4, -5),
                                                              (4, -5)))
     L = L.round().astype(int)
     L[:, :, 0] += 20
     L[:, :, 1] = self.height - 20 - L[:, :, 1]
     line = self.pixmap.draw_line
     colors = ([self.black_gc] * 3 + [self.red] * 2 + [self.green] * 2 +
               [self.blue] * 3)
     for i in L[:, 1, 2].argsort():
         (a, b), (c, d) = L[i, :, :2]
         line(colors[i], a, b, c, d)
Beispiel #21
0
    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)
Beispiel #22
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)))
Beispiel #23
0
    def initialize(self, images, filenames=None, init_magmom=False):

        self.natoms = len(images[0])
        self.nimages = len(images)
        if hasattr(images[0], 'get_shapes'):
            self.shapes = images[0].get_shapes()
            self.Q = []
        else:
            self.shapes = None

        if filenames is None:
            filenames = [None] * self.nimages
        self.filenames = filenames
        self.P = np.empty((self.nimages, self.natoms, 3))
        self.V = np.empty((self.nimages, self.natoms, 3))
        self.E = np.empty(self.nimages)
        self.K = np.empty(self.nimages)
        self.F = np.empty((self.nimages, self.natoms, 3))
        self.M = np.empty((self.nimages, self.natoms))
        self.T = np.empty((self.nimages, self.natoms), int)
        self.A = np.empty((self.nimages, 3, 3))
        self.Z = images[0].get_atomic_numbers()
        self.pbc = images[0].get_pbc()
        self.covalent_radii = covalent_radii
        config = read_defaults()
        if config['covalent_radii'] is not None:
            for data in config['covalent_radii']:
                self.covalent_radii[data[0]] = data[1]
        warning = False
        for i, atoms in enumerate(images):
            natomsi = len(atoms)
            if (natomsi != self.natoms
                    or (atoms.get_atomic_numbers() != self.Z).any()):
                raise RuntimeError('Can not handle different images with ' +
                                   'different numbers of atoms or different ' +
                                   'kinds of atoms!')
            self.P[i] = atoms.get_positions()
            self.V[i] = atoms.get_velocities()

            if hasattr(self, 'Q'):
                for q in atoms.get_quaternions():
                    self.Q.append(Quaternion(q))

            self.A[i] = atoms.get_cell()
            if (atoms.get_pbc() != self.pbc).any():
                warning = True
            try:
                self.E[i] = atoms.get_potential_energy()
            except RuntimeError:
                self.E[i] = np.nan
            self.K[i] = atoms.get_kinetic_energy()
            try:
                self.F[i] = atoms.get_forces(apply_constraint=False)
            except RuntimeError:
                self.F[i] = np.nan
            try:
                if init_magmom:
                    self.M[i] = atoms.get_initial_magnetic_moments()
                else:
                    self.M[i] = atoms.get_magnetic_moments()
            except (RuntimeError, AttributeError):
                self.M[i] = atoms.get_initial_magnetic_moments()

            # added support for tags
            try:
                self.T[i] = atoms.get_tags()
            except RuntimeError:
                self.T[i] = 0

        if warning:
            print('WARNING: Not all images have the same bondary conditions!')

        self.selected = np.zeros(self.natoms, bool)
        self.selected_ordered = []
        self.atoms_to_rotate_0 = np.zeros(self.natoms, bool)
        self.visible = np.ones(self.natoms, bool)
        self.nselected = 0
        self.set_dynamic(constraints=images[0].constraints)
        self.repeat = np.ones(3, int)
        self.set_radii(config['radii_scale'])
Beispiel #24
0
 def quaternion(self):
     if self._quat is None:
         self._quat = _evecs_2_quat([self._evecs])[0]
     return Quaternion(self._quat.q)
Beispiel #25
0
    # 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
    
# First: test that rotations DO work
for i in range(10):
    # 10 random tests
        
    rotm = rand_rotm()

    q = Quaternion.from_matrix(rotm)

    # Now test this with a vector
    v = np.random.random(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)