Exemplo n.º 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))
Exemplo n.º 2
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)
Exemplo n.º 3
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
Exemplo n.º 4
0
    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]))
Exemplo n.º 5
0
Arquivo: view.py Projeto: 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)
Exemplo n.º 6
0
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
Exemplo n.º 7
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
Exemplo n.º 8
0
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))
Exemplo n.º 9
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
Exemplo n.º 10
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)
Exemplo n.º 11
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'])
Exemplo n.º 12
0
 def quaternion(self):
     if self._quat is None:
         self._quat = _evecs_2_quat([self._evecs])[0]
     return Quaternion(self._quat.q)