예제 #1
0
    def reorient_molecule(self, nuclei_list):
        first_nuclei = nuclei_list.pop(0)
        coordinates = first_nuclei.coordinates
        first_nuclei.coordinates = (0, 0, 0)

        for nuclei in nuclei_list:
            x = nuclei.coordinates[0] - coordinates[0]
            y = nuclei.coordinates[1] - coordinates[1]
            z = nuclei.coordinates[2] - coordinates[2]
            nuclei.coordinates = (x, y, z)

        if len(nuclei_list) >= 1:
            second_nuclei = nuclei_list[0]
            coordinates = normalize(second_nuclei.coordinates)

            quaternion = create_quaternion(
                (-coordinates[1], coordinates[0], 0.0), -theta(coordinates))
            for nuclei in nuclei_list:
                nuclei.coordinates = quaternion_rotation(
                    quaternion, nuclei.coordinates)

        if len(nuclei_list) >= 2:
            third_nuclei = nuclei_list[1]
            coordinates = normalize(third_nuclei.coordinates)

            quaternion = create_quaternion((0.0, 0.0, 1.0),
                                           -phi(coordinates) + np.pi / 2)
            for nuclei in nuclei_list:
                nuclei.coordinates = quaternion_rotation(
                    quaternion, nuclei.coordinates)

        return [first_nuclei], nuclei_list
예제 #2
0
    def standard_orientation(self, nuclei_array, rotation_symmetry,
                             reflection_symmetry):
        vector_i = vector_j = (0.0, 0.0, 0.0)

        if len(rotation_symmetry) > 1:
            highest_n_folds = heapq.nlargest(
                2, [rotation.fold for rotation in rotation_symmetry])
            for rotation in rotation_symmetry:
                if rotation.fold == highest_n_folds[0]:
                    vector_i = rotation.vector
                    break
            for rotation in rotation_symmetry:
                if rotation.fold == highest_n_folds[
                        1] and rotation.vector != vector_i:
                    vector_j = rotation.vector
                    break

        if len(rotation_symmetry) == 1:
            vector_i = rotation_symmetry[0].vector
            for reflection in reflection_symmetry:
                if phi(reflection.vector) > self.error:
                    vector_j = reflection.vector
                    break

        if len(rotation_symmetry) == 0 and len(reflection_symmetry) > 1:
            vector_i = reflection_symmetry[0].vector
            vector_j = reflection_symmetry[1].vector

        if rho(nuclei_array[0].coordinates) > 1e-3:
            i = 0
        else:
            i = 1

        if len(rotation_symmetry) == 0 and len(reflection_symmetry) == 1:
            vector_i = reflection_symmetry[0].vector
            vector_j = nuclei_array[i].coordinates

        if len(rotation_symmetry) == 0 and len(reflection_symmetry) == 0:
            vector_i = nuclei_array[i].coordinates
            vector_j = nuclei_array[i + 1].coordinates

        if rho(vector_i) <= self.error:
            vector_i = (1.0, 0.0, 0.0)

        quaternion_i = create_quaternion((-vector_i[1], vector_i[0], 0.0),
                                         -theta(vector_i))
        quaternion_j = create_quaternion((0.0, 0.0, 1.0), -phi(vector_j))
        quaternion = quaternion_multi(quaternion_j, quaternion_i)

        for rotation in rotation_symmetry:
            rotation.vector = quaternion_rotation(quaternion, rotation.vector)
        for reflection in reflection_symmetry:
            reflection.vector = quaternion_rotation(quaternion,
                                                    reflection.vector)
        for nuclei in nuclei_array:
            nuclei.coordinates = quaternion_rotation(quaternion,
                                                     nuclei.coordinates)

        return nuclei_array, rotation_symmetry, reflection_symmetry
 def test_create_quaternion_returns_quaternion_for_45_degree_rotation_around_x_axis(
         self):
     axis_of_rotation = (1.0, 0.0, 0.0)
     theta = pi / 4
     quaternion = create_quaternion(axis_of_rotation, theta)
     testing.assert_array_almost_equal(quaternion,
                                       (0.923880, 0.382683, 0.0, 0.0), 6)
 def test_create_quaternion_returns_quaternion_for_90_degree_rotation_around_y_axis(
         self):
     axis_of_rotation = (0.0, 1.0, 0.0)
     theta = pi / 2
     quaternion = create_quaternion(axis_of_rotation, theta)
     testing.assert_array_almost_equal(quaternion,
                                       (0.707107, 0.0, 0.707107, 0.0), 6)
 def test_rotation_of_unit_y_vector_with_axis_of_rotation_y_by_90_degrees(
         self):
     theta = pi / 2
     axis_of_rotation = (0, 1, 0)
     x_vector = (1, 0, 0)
     quaternion = create_quaternion(axis_of_rotation, theta)
     rotated_vector = quaternion_rotation(quaternion, x_vector)
     testing.assert_array_almost_equal(rotated_vector, (0, 0, -1), 6)
 def test_rotation_of_unit_z_vector_with_axis_of_rotation_x_by_45_degrees(
         self):
     theta = pi / 4
     axis_of_rotation = (1, 0, 0)
     z_vector = (0, 0, -1)
     quaternion = create_quaternion(axis_of_rotation, theta)
     rotated_vector = quaternion_rotation(quaternion, z_vector)
     testing.assert_array_almost_equal(rotated_vector,
                                       (0, 0.707107, -0.707107), 6)
예제 #7
0
    def brute_force_reflection_symmetry(self, nuclei_array, rotation_symmetry,
                                        vertices, cross_vertices_vertices,
                                        cross_edge_vertices):

        # rotate all orthogonal vectors by principal axis by half it's n-fold angle
        vector_cross = self.remove_duplicate(vertices +
                                             cross_vertices_vertices +
                                             cross_edge_vertices)

        vectors_cross_rotated = []
        if len(rotation_symmetry) > 0:

            highest_symmetries = []
            highest_n_fold = max(
                [rotation.fold for rotation in rotation_symmetry])
            for rotation in rotation_symmetry:
                if rotation.fold == highest_n_fold:
                    highest_symmetries.append(rotation)

            for highest_symmetry in highest_symmetries:
                quaternion_list = []
                vector = highest_symmetry.vector
                for i in range(1, highest_symmetry.fold):
                    theta_i = pi * i / highest_symmetry.fold
                    quaternion = create_quaternion(vector, theta_i)
                    quaternion_list.append(quaternion)

                for quaternion in quaternion_list:
                    for orthogonal_vector_i in vector_cross:
                        orthogonal_vector_j = quaternion_rotation(
                            quaternion, orthogonal_vector_i)
                        vectors_cross_rotated.append(orthogonal_vector_j)

        reflection_planes = []
        if len(vector_cross) > 0:

            total_vectors_cross = cross_vertices_vertices + vectors_cross_rotated
            vectors_reflection_plane = self.remove_duplicate(
                total_vectors_cross)

            planes_of_reflection = []
            for planes in vectors_reflection_plane:
                householder_matrix = ReflectionSymmetry(planes)
                planes_of_reflection.append(householder_matrix)

            # check each reflection
            for plane_of_reflection in planes_of_reflection:
                if self.check_symmetry_operation(nuclei_array,
                                                 plane_of_reflection):
                    reflection_planes.append(plane_of_reflection)

        return reflection_planes
예제 #8
0
    def operate(self, coordinate):
        """Rotates a point around the axis of rotation for a angle of 2 * pi / self.fold

        Parameters
        ----------
        coordinate : Tuple[float, float, float]

        Returns
        -------
        : Tuple[float, float, float]

        """
        angle = 2 * pi / self.fold
        quaternion = create_quaternion(self.vector, angle)
        return quaternion_rotation(quaternion, coordinate)
    def operate(self, coordinate):
        """Rotates a point around the axis of rotation for a angle of 2 * pi / self.fold and then inverts.

        Parameters
        ----------
        coordinate : Tuple[float, float, float]

        Returns
        -------
        : Tuple[float, float, float]

        """
        angle = 2 * pi / self.fold
        quaternion = create_quaternion(self.vector, angle)
        householder_matrix = create_householder_matrix(self.vector)
        x, y, z = householder_matrix_reflection(
            quaternion_rotation(quaternion, coordinate), householder_matrix)
        return x, y, z
예제 #10
0
    def int_operate(self, coordinate):
        """Returns the rotation symmetry operation on a coordinate but returns a tuple of ints.

        This method is useful for seeing how the symmetry operation affects the sign of a gaussian functions integral
        exponents.

        Parameters
        ----------
        coordinate : Tuple[float, float, float]

        Returns
        -------
        : Tuple[int, int, int]

        """
        angle = 2 * pi / self.fold
        quaternion = create_quaternion(self.vector, angle)
        x, y, z = quaternion_rotation(quaternion, coordinate)
        return int(round(x, 1)), int(round(y, 1)), int(round(z, 1))