Exemple #1
0
    def test_nontrivial_orientations(self):
        """Ensure that orientations are applied to the right particles."""
        box = self.get_cubic_box(6)
        points = np.array([[-1.0, 0.0, 0.0]], dtype=np.float32)
        query_points = np.array([[0.9, 0.1, 0.0]], dtype=np.float32)

        for angles in ([0], [np.pi / 4]):
            for query_angles in ([0.01], [np.pi / 4 + 0.01]):
                max_width = 2
                nbins = 4
                self.limits = (max_width, ) * 2
                self.bins = (nbins, nbins, nbins)

                pmft = freud.pmft.PMFTXYT(max_width, max_width, nbins)
                pmft.compute((box, points), angles, query_points, query_angles)

                query_orientation = rowan.from_axis_angle([0, 0, 1],
                                                          query_angles[0])
                orientation = rowan.from_axis_angle([0, 0, 1], angles[0])

                assert tuple(np.asarray(np.where(
                    pmft.bin_counts)).flatten()) == self.get_bin(
                        query_points[0], points[0], query_orientation,
                        orientation)
                assert np.sum(pmft.bin_counts) == 1
    def test_disordered(self):
        # do not need positions, just orientations
        N = 1000
        axes = np.zeros(shape=(N, 3), dtype=np.float32)
        angles = np.zeros(shape=N, dtype=np.float32)
        # pick axis at random
        ax_list = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0],
                            [1, 0, 1], [0, 1, 1], [1, 1, 1]],
                           dtype=np.float32)
        ax_list /= np.linalg.norm(ax_list, axis=-1)[:, np.newaxis]

        for i in range(N):
            axes[i] = ax_list[i % ax_list.shape[0]]

        # generate disordered orientations
        np.random.seed(0)
        angles = np.random.uniform(low=np.pi / 4.0, high=np.pi / 2.0, size=N)
        orientations = rowan.from_axis_angle(axes, angles)

        # create cubatic object
        cubatic = freud.order.Cubatic(5.0, 0.001, 0.95, 10)
        cubatic.compute(orientations)
        # get the op
        op = cubatic.order

        pop = cubatic.particle_order
        op_max = np.nanmax(pop)

        npt.assert_array_less(op, 0.3, err_msg="Cubatic Order is > 0.3")
        npt.assert_array_less(
            op_max,
            0.2,
            err_msg="per particle order parameter value is too high")
Exemple #3
0
def test_convex_polygon_distance_to_surface_unit_area_ngon_rotated(shape, ):
    """Check shape distance consistency with the final edge wraparound."""
    theta = np.linspace(0, 2 * np.pi, 1000000)

    # Try a positive rotation.
    verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], 0.1), shape.vertices)
    shape = ConvexPolygon(verts)
    distance = shape.distance_to_surface(theta)
    assert_distance_to_surface_2d(shape, theta, distance)

    # Now try a negative rotation.
    verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], -0.2),
                         shape.vertices)
    shape = ConvexPolygon(verts)
    distance = shape.distance_to_surface(theta)
    assert_distance_to_surface_2d(shape, theta, distance)
Exemple #4
0
    def test_equivalent(self):
        """Perform a rotation and ensure that we can recover it"""
        # Test on an octahedron
        points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1],
                  [0, 0, -1]]

        # This is just a selected subset
        eq = [
            from_axis_angle([0, 0, 1], a)
            for a in [0, np.pi / 2, np.pi, 3 * np.pi / 2]
        ]

        np.random.seed(0)
        rotation = random.rand(1)
        translation = np.random.rand(1, 3)

        transformed_points = rotate(rotation, points) + translation

        q, t = mapping.procrustes(points,
                                  transformed_points,
                                  equivalent_quaternions=eq)

        # Sort the points in a deterministic manner for comparison
        recovered_points = rotate(q, points) + t
        ordered_recovered_points = recovered_points[np.argsort(
            recovered_points[:, 0])]
        ordered_transformed_points = transformed_points[np.argsort(
            transformed_points[:, 0])]

        self.assertTrue(
            np.allclose(ordered_recovered_points, ordered_transformed_points))
Exemple #5
0
    def test_icp_exact(self):
        """Ensure that ICP is exact for corresponding inputs"""
        # Note that we do not bother to test the non-unique matching since we
        # know it provides very poor results.
        np.random.seed(0)

        # First test using unique matching, which should work
        for i in range(2, 6):
            num_points = 2**i

            points = np.random.rand(num_points, 3)
            rotation = from_axis_angle([0.3, 0.3, 0.3], 0.3)
            translation = np.random.rand(1, 3)

            transformed_points = rotate(rotation, points) + translation

            q, t, indices = mapping.icp(points,
                                        transformed_points,
                                        return_indices=True)
            q = from_matrix(q)

            # In the case of just two points, the mapping is not unique,
            # so we don't check the mapping itself, just the result.
            if i > 1:
                self.assertTrue(
                    np.logical_or(
                        np.allclose(rotation, q),
                        np.allclose(rotation, -q),
                    ))
                self.assertTrue(np.allclose(translation, t))
            self.assertTrue(
                np.allclose(transformed_points,
                            rotate(q, points[indices]) + t))
Exemple #6
0
    def test_icp_mismatched(self):
        """See how ICP works for non-corresponding inputs. Have set some
        reasonable threshold for testing purposes."""
        np.random.seed(0)

        # First test using unique matching, which should work
        for i in range(2, 6):
            num_points = 2**i

            points = np.random.rand(num_points, 3)
            rotation = from_axis_angle([0.3, 0.3, 0.3], 0.3)
            translation = np.random.rand(1, 3)

            permutation = np.random.permutation(num_points)
            transformed_points = rotate(rotation,
                                        points[permutation]) + translation

            q, t, indices = mapping.icp(points,
                                        transformed_points,
                                        return_indices=True)
            q = from_matrix(q)

            deltas = transformed_points - (rotate(q, points[indices]) + t)
            norms = np.linalg.norm(deltas, axis=-1)
            # This is purely a heuristic, since we can't guarantee exact matches
            self.assertTrue(np.mean(norms) < 0.5)
Exemple #7
0
    def s3_unitcell(f):
        """Open solid unit cell

        Args
        ----
        f : float
            The patch offset statepoint parameter

        Assumes f = ±1 corresponds to the patch on the vertex

        """
        import hoomd
        N = 2
        a1 = np.array([1, 0, 0])
        theta = np.deg2rad(60)
        a2 = np.array([np.cos(theta), np.sin(theta), 0])
        a3 = np.array([0, 0, 1])
        pos = [[0, 0, 0], 1 / 3 * (a1 + a2)]
        x = f * 90
        orientations = np.deg2rad(np.array([-30 + x, 150 + x]))
        orientations = [rowan.from_axis_angle(a3, t) for t in orientations]
        return hoomd.lattice.unitcell(N,
                                      a1,
                                      a2,
                                      a3,
                                      dimensions=2,
                                      position=pos,
                                      orientation=orientations)
Exemple #8
0
def test_distance_to_surface_unit_area_ngon_vertex_distance(shape, ):
    """Check that the actual distances are computed correctly."""
    distances = np.linalg.norm(shape.vertices - shape.center, axis=-1)
    theta = np.linspace(0, 2 * np.pi, shape.num_vertices + 1)
    assert np.allclose(shape.distance_to_surface(theta)[:-1], distances)

    # Try a positive rotation.
    verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], 0.1), shape.vertices)
    shape = ConvexPolygon(verts)
    assert np.allclose(shape.distance_to_surface(theta + 0.1)[:-1], distances)

    # Now try a negative rotation.
    verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], -0.2),
                         shape.vertices)
    shape = ConvexPolygon(verts)
    assert np.allclose(shape.distance_to_surface(theta - 0.1)[:-1], distances)
Exemple #9
0
 def test_single(self):
     """Test rotation about an axis."""
     v = np.array([1, 0, 0])
     theta = np.pi
     quats = rowan.from_axis_angle(v, theta)
     self.assertTrue(quats.shape[:-1] == v.shape[:-1])
     self.assertTrue(np.allclose(quats, np.array([0, 1, 0, 0])))
Exemple #10
0
def quaternion_from_axis_angle(x, y, z, theta):
    """Generate a quaternion from axis [x, y, z] and angle theta."""
    if x == y == z == 0:
        return np.array([1, 0, 0, 0])
    axis = np.array([x, y, z])
    axis /= np.linalg.norm(axis)
    return rowan.from_axis_angle(axis, theta)
Exemple #11
0
    def orbit(self, yaw=0, pitch=0, roll=0, factor=-0.0025, slight=False):
        """Orbit the camera about the look_at point."""
        if slight:
            factor = factor * 0.1

        basis = numpy.array(self._start_camera.basis)

        q1 = rowan.from_axis_angle(basis[1, :], factor * yaw)
        q2 = rowan.from_axis_angle(basis[0, :], factor * pitch)
        q3 = rowan.from_axis_angle(basis[2, :], factor * roll)
        q = rowan.multiply(q2, rowan.multiply(q1, q3))

        v = self._start_camera.position - self._start_camera.look_at
        v = rowan.rotate(q, v)

        self.camera.position = self._start_camera.look_at + v
        self.camera.up = rowan.rotate(q, basis[1, :])
    def test_ordered(self):
        # do not need positions, just orientations
        N = 1000
        axes = np.zeros(shape=(N, 3), dtype=np.float32)
        angles = np.zeros(shape=N, dtype=np.float32)
        axes[:, 2] = 1.0

        # generate similar angles
        np.random.seed(1030)
        angles = np.random.uniform(low=0.0, high=0.05, size=N)
        orientations = rowan.from_axis_angle(axes, angles)

        # create cubatic object
        t_initial = 5.0
        t_final = 0.001
        scale = 0.95
        n_replicates = 10
        cop = freud.order.Cubatic(t_initial, t_final, scale, n_replicates)

        # Test access
        with self.assertRaises(AttributeError):
            cop.order
        with self.assertRaises(AttributeError):
            cop.orientation
        with self.assertRaises(AttributeError):
            cop.particle_order
        with self.assertRaises(AttributeError):
            cop.global_tensor
        with self.assertRaises(AttributeError):
            cop.cubatic_tensor

        cop.compute(orientations)

        # Test access
        cop.order
        cop.orientation
        cop.particle_order
        cop.global_tensor
        cop.cubatic_tensor

        # Test values of the OP
        self.assertAlmostEqual(cop.order,
                               1,
                               places=2,
                               msg="Cubatic Order is not approx. 1")
        self.assertGreater(np.nanmin(cop.particle_order),
                           0.9,
                           msg="Per particle order parameter value is too low")

        # Test attributes
        self.assertAlmostEqual(cop.t_initial, t_initial)
        self.assertAlmostEqual(cop.t_final, t_final)
        self.assertAlmostEqual(cop.scale, scale)

        # Test shapes for the tensor since we can't ensure values.
        self.assertEqual(cop.orientation.shape, (4, ))
        self.assertEqual(cop.cubatic_tensor.shape, (3, 3, 3, 3))
        self.assertEqual(cop.global_tensor.shape, (3, 3, 3, 3))
Exemple #13
0
 def test_multiple_vectors(self):
     """Test multiple vectors against an angle."""
     v = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
     theta = np.pi
     quats = rowan.from_axis_angle(v, theta)
     self.assertTrue(quats.shape[:-1] == v.shape[:-1])
     self.assertTrue(
         np.allclose(quats,
                     np.array([[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])))
Exemple #14
0
 def get_bin(query_point, point, query_point_angle, point_angle):
     r_ij = point - query_point
     orientation = rowan.from_axis_angle([0, 0, 1], -point_angle)
     rot_r_ij = rowan.rotate(orientation, r_ij)
     xy_bins = np.floor(
         (rot_r_ij[:2] + [maxX, maxY]) / [dx, dy]).astype(np.int32)
     angle_bin = np.floor(
         ((query_point_angle - np.arctan2(-r_ij[1], -r_ij[0])) %
          (2. * np.pi)) / dT).astype(np.int32)
     return [xy_bins[0], xy_bins[1], angle_bin]
    def test_ordered(self):
        # do not need positions, just orientations
        N = 1000
        axes = np.zeros(shape=(N, 3), dtype=np.float32)
        angles = np.zeros(shape=N, dtype=np.float32)
        axes[:, 2] = 1.0

        # generate similar angles
        np.random.seed(1030)
        angles = np.random.uniform(low=0.0, high=0.05, size=N)
        orientations = rowan.from_axis_angle(axes, angles)

        # create cubatic object
        t_initial = 5.0
        t_final = 0.001
        scale = 0.95
        n_replicates = 10
        cop = freud.order.Cubatic(t_initial, t_final, scale, n_replicates)

        # Test access
        with pytest.raises(AttributeError):
            cop.order
        with pytest.raises(AttributeError):
            cop.orientation
        with pytest.raises(AttributeError):
            cop.particle_order
        with pytest.raises(AttributeError):
            cop.global_tensor
        with pytest.raises(AttributeError):
            cop.cubatic_tensor

        cop.compute(orientations)

        # Test access
        cop.order
        cop.orientation
        cop.particle_order
        cop.global_tensor
        cop.cubatic_tensor

        # Test values of the OP
        assert round(abs(cop.order - 1),
                     2) == 0, "Cubatic Order is not approx. 1"
        assert (np.nanmin(cop.particle_order) >
                0.9), "Per particle order parameter value is too low"

        # Test attributes
        assert round(abs(cop.t_initial - t_initial), 7) == 0
        assert round(abs(cop.t_final - t_final), 7) == 0
        assert round(abs(cop.scale - scale), 7) == 0

        # Test shapes for the tensor since we can't ensure values.
        assert cop.orientation.shape == (4, )
        assert cop.cubatic_tensor.shape == (3, 3, 3, 3)
        assert cop.global_tensor.shape == (3, 3, 3, 3)
Exemple #16
0
def gen_sym_quats(group):
    """Generate symmetric quaternions for a set of point groups."""
    operations = symgroups[group]
    quats = []
    for operation in operations:
        qtemp = rowan.from_axis_angle(axes=operation[1],
                                      angles=2 * np.pi / operation[0])
        quats.append(qtemp.tolist())
        quats.append(rowan.multiply([-1, 0, 0, 0], qtemp).tolist())

    return quats
Exemple #17
0
 def test_multiple(self):
     """Test multiple vectors against multiple angles"""
     v = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
     theta = np.array([np.pi, np.pi / 2, np.pi / 3])
     quats = rowan.from_axis_angle(v, theta)
     self.assertTrue(quats.shape[:-1] == v.shape[:-1])
     self.assertTrue(
         np.allclose(
             quats,
             np.array([[0, 1, 0, 0], [np.sqrt(2) / 2, 0,
                                      np.sqrt(2) / 2, 0],
                       [np.sqrt(3) / 2, 0, 0, 1 / 2]])))
Exemple #18
0
def test_inertia_tensor(square):
    """Test the inertia tensor calculation."""
    square.center = (0, 0, 0)
    assert np.sum(square.inertia_tensor > 1e-6) == 1
    assert square.inertia_tensor[2, 2] == 1 / 6

    # Validate yz plane.
    rotation = rowan.from_axis_angle([0, 1, 0], np.pi / 2)
    rotated_verts = rowan.rotate(rotation, square.vertices)
    rotated_square = ConvexPolygon(rotated_verts)
    assert np.sum(rotated_square.inertia_tensor > 1e-6) == 1
    assert rotated_square.inertia_tensor[0, 0] == 1 / 6

    # Validate xz plane.
    rotation = rowan.from_axis_angle([1, 0, 0], np.pi / 2)
    rotated_verts = rowan.rotate(rotation, square.vertices)
    rotated_square = ConvexPolygon(rotated_verts)
    assert np.sum(rotated_square.inertia_tensor > 1e-6) == 1
    assert rotated_square.inertia_tensor[1, 1] == 1 / 6

    # Validate translation along each axis.
    delta = 2
    area = square.area
    for i in range(3):
        translation = [0] * 3
        translation[i] = delta
        translated_verts = square.vertices + translation
        translated_square = ConvexPolygon(translated_verts)
        offdiagonal_tensor = translated_square.inertia_tensor.copy()
        diag_indices = np.diag_indices(3)
        offdiagonal_tensor[diag_indices] = 0
        assert np.sum(offdiagonal_tensor > 1e-6) == 0
        expected_diagonals = [0, 0, 1 / 6]
        for j in range(3):
            if i != j:
                expected_diagonals[j] += area * delta * delta
        assert np.allclose(
            np.diag(translated_square.inertia_tensor), expected_diagonals
        )
Exemple #19
0
    def test_complex(self):
        """Test higher dimensions and broadcasting."""
        # Various ways of producing the same output
        expected_output = (np.array([
            [0, 1, 0, 0],
            [np.sqrt(2) / 2, 0, np.sqrt(2) / 2, 0],
            [np.sqrt(3) / 2, 0, 0, 1 / 2],
        ])[np.newaxis, np.newaxis, ...].repeat(2, axis=0).repeat(2, axis=1))

        # Matching array shapes (no broadcasing at all)
        v = (np.array([[1, 0, 0], [0, 1, 0],
                       [0, 0, 1]])[np.newaxis, np.newaxis,
                                   ...].repeat(2, axis=0).repeat(2, axis=1))
        theta = (np.array([np.pi, np.pi / 2,
                           np.pi / 3])[np.newaxis, np.newaxis,
                                       ...].repeat(2, axis=0).repeat(2,
                                                                     axis=1))

        quats = rowan.from_axis_angle(v, theta)
        self.assertTrue(quats.shape[:-1] == v.shape[:-1])
        self.assertTrue(np.allclose(quats, expected_output))

        # Broadcasting in theta
        theta_reduced = theta[0, :, ...]
        quats = rowan.from_axis_angle(v, theta_reduced)
        self.assertTrue(quats.shape[:-1] == v.shape[:-1])
        self.assertTrue(np.allclose(quats, expected_output))

        # Broadcasting in v
        v_reduced = v[:, 0, ...]
        quats = rowan.from_axis_angle(v_reduced, theta)
        self.assertTrue(quats.shape[:-1] == v.shape[:-1])
        self.assertTrue(np.allclose(quats, expected_output))

        # Broadcasting in both
        quats = rowan.from_axis_angle(v_reduced[:, np.newaxis, ...],
                                      theta_reduced[np.newaxis, :, ...])
        self.assertTrue(quats.shape[:-1] == v.shape[:-1])
        self.assertTrue(np.allclose(quats, expected_output))
Exemple #20
0
    def test_quaternions(self):
        """Test that using quaternions as angles works."""
        boxSize = 8
        box = freud.box.Box.square(boxSize)
        points = np.array([[0, 0, 0]], dtype=np.float32)
        query_points = np.array([[1.1, 0.0, 0.0], [-1.2, 0.0, 0.0],
                                 [0.0, 1.3, 0.0], [0.0, -1.4, 0.0]],
                                dtype=np.float32)
        angles = np.array([0.0] * points.shape[0], dtype=np.float32)
        query_angles = np.array([0.0] * query_points.shape[0],
                                dtype=np.float32)

        orientations = rowan.from_axis_angle([0, 0, 1], angles)
        query_orientations = rowan.from_axis_angle([0, 0, 1], query_angles)

        max_width = 3
        nbins = 3
        pmft = freud.pmft.PMFTXY(max_width, max_width, nbins)
        pmft.compute((box, points),
                     orientations,
                     query_points,
                     neighbors={
                         'mode': 'nearest',
                         'num_neighbors': 1
                     })
        # Now every point in query_points will find the origin as a neighbor.
        npt.assert_array_equal(pmft.bin_counts,
                               [[0, 1, 0], [1, 0, 1], [0, 1, 0]])
        # Now there will be only one neighbor for the single point.
        pmft.compute((box, query_points),
                     query_orientations,
                     points,
                     neighbors={
                         'mode': 'nearest',
                         'num_neighbors': 1
                     })
        npt.assert_array_equal(pmft.bin_counts,
                               [[0, 0, 0], [0, 0, 0], [0, 1, 0]])
    def test_perfect(self):
        """Test perfectly aligned systems with different molecular axes"""
        N = 10000
        axes = np.zeros(shape=(N, 3), dtype=np.float32)
        angles = np.zeros(shape=N, dtype=np.float32)
        axes[:, 0] = 1.0
        orientations = rowan.from_axis_angle(axes, angles)

        # Test for parallel to molecular axis
        u = np.array([1, 0, 0])
        op_parallel = freud.order.Nematic(u)

        # Test access
        with self.assertRaises(AttributeError):
            op_parallel.order
        with self.assertRaises(AttributeError):
            op_parallel.director
        with self.assertRaises(AttributeError):
            op_parallel.particle_tensor
        with self.assertRaises(AttributeError):
            op_parallel.nematic_tensor

        op_parallel.compute(orientations)

        # Test access
        op_parallel.order
        op_parallel.director
        op_parallel.particle_tensor
        op_parallel.nematic_tensor

        self.assertTrue(op_parallel.order == 1)
        npt.assert_equal(op_parallel.director, u)
        npt.assert_equal(
            op_parallel.nematic_tensor, np.diag([1, -0.5, -0.5]))
        npt.assert_equal(
            op_parallel.nematic_tensor, np.mean(
                op_parallel.particle_tensor, axis=0))

        # Test for perpendicular to molecular axis
        u = np.array([0, 1, 0])
        op_perp = freud.order.Nematic(u)
        op_perp.compute(orientations)

        self.assertEqual(op_perp.order, 1)
        npt.assert_equal(op_perp.director, u)
        npt.assert_equal(
            op_perp.nematic_tensor, np.diag([-0.5, 1, -0.5]))
Exemple #22
0
    def test_orientation_with_fewer_query_points(self):
        """The orientations should be associated with the query points if they
        are provided. Ensure that this works when the number of points and
        query points differ."""
        L = 8
        box = freud.box.Box.cube(L)
        # Don't place the points at exactly distances of 0/1 apart to avoid any
        # ambiguity when the distances fall on the bin boundaries.
        points = np.array([[0.1, 0.1, 0], [0.89, 0.89, 0]], dtype=np.float32)
        points2 = np.array([[1, 0, 0]], dtype=np.float32)
        angles = np.array([np.deg2rad(0)] * points.shape[0], dtype=np.float32)
        quats = rowan.from_axis_angle([0, 0, 1], angles)
        angles2 = np.array([np.deg2rad(0)] * points2.shape[0],
                           dtype=np.float32)
        quats2 = rowan.from_axis_angle([0, 0, 1], angles2)

        def points_to_set(bin_counts):
            """Extract set of unique occupied bins from pmft bin counts."""
            return set(zip(*np.asarray(np.where(bin_counts)).tolist()))

        max_width = 3
        cells_per_unit_length = 4
        nbins = max_width * cells_per_unit_length
        pmft = freud.pmft.PMFTXYZ(max_width, max_width, max_width, nbins)

        # There should be two nonzero bins:
        #     dx=-0.9, dy=0.1: bin (4, 6).
        #     dx=-0.11, dy=0.89: bin (5, 7).
        pmft.compute(
            (box, points),
            quats2,
            points2,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 2
            },
        )
        npt.assert_array_equal(points_to_set(pmft.bin_counts), {(4, 6, 6),
                                                                (5, 7, 6)})

        # Now the sets of points are swapped, so:
        #     dx=0.9, dy=-0.1: bin (7, 5).
        #     dx=0.11, dy=-0.89: bin (6, 4).
        pmft.compute(
            (box, points2),
            quats,
            points,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 2
            },
        )
        npt.assert_array_equal(points_to_set(pmft.bin_counts), {(7, 5, 6),
                                                                (6, 4, 6)})

        # Apply a rotation to whichever point is provided as a query_point by
        # 45 degrees (easiest to picture if you think of each point as a
        # square).
        angles2 = np.array([np.deg2rad(45)] * points2.shape[0],
                           dtype=np.float32)
        quats2 = rowan.from_axis_angle([0, 0, 1], angles2)

        # Determine the relative position of the point when points2 is rotated
        # by 45 degrees. Since we're undoing the orientation of the orientation
        # of the particle, we have to conjugate the quaternion.
        bond_vector = rowan.rotate(rowan.conjugate(quats2), points - points2)
        bins = ((bond_vector + max_width) * cells_per_unit_length /
                2).astype(int)
        bins = {tuple(x) for x in bins}

        pmft.compute(
            (box, points),
            quats2,
            points2,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 2
            },
        )
        npt.assert_array_equal(points_to_set(pmft.bin_counts), bins)
Exemple #23
0
    def test_orientation_with_query_points(self):
        """The orientations should be associated with the query points if they
        are provided."""
        L = 8
        box = freud.box.Box.cube(L)
        # Don't place the points at exactly distances of 0/1 apart to avoid any
        # ambiguity when the distances fall on the bin boundaries.
        points = np.array([[0.1, 0.1, 0]], dtype=np.float32)
        points2 = np.array([[1, 0, 0]], dtype=np.float32)
        angles = np.array([np.deg2rad(0)] * points2.shape[0], dtype=np.float32)
        quats = rowan.from_axis_angle([0, 0, 1], angles)

        max_width = 3
        cells_per_unit_length = 4
        nbins = max_width * cells_per_unit_length
        pmft = freud.pmft.PMFTXYZ(max_width, max_width, max_width, nbins)

        # In this case, the only nonzero bin should be in the bin corresponding
        # to dx=-0.9, dy=0.1, which is (4, 6).
        pmft.compute(
            (box, points),
            quats,
            points2,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 1
            },
        )
        npt.assert_array_equal(
            np.asarray(np.where(pmft.bin_counts)).squeeze(), (4, 6, 6))

        # Now the sets of points are swapped, so dx=0.9, dy=-0.1, which is
        # (7, 5).
        pmft.compute(
            (box, points2),
            quats,
            points,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 1
            },
        )
        npt.assert_array_equal(
            np.asarray(np.where(pmft.bin_counts)).squeeze(), (7, 5, 6))

        # Apply a rotation to whichever point is provided as a query_point by
        # 45 degrees (easiest to picture if you think of each point as a
        # square).
        angles = np.array([np.deg2rad(45)] * points2.shape[0],
                          dtype=np.float32)
        quats = rowan.from_axis_angle([0, 0, 1], angles)

        # Determine the relative position of the point when points2 is rotated
        # by 45 degrees. Since we're undoing the orientation of the orientation
        # of the particle, we have to conjugate the quaternion.
        bond_vector = rowan.rotate(rowan.conjugate(quats), points - points2)
        bins = ((bond_vector + max_width) * cells_per_unit_length /
                2).astype(int)

        pmft.compute(
            (box, points),
            quats,
            points2,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 1
            },
        )
        npt.assert_array_equal(
            np.asarray(np.where(pmft.bin_counts)).squeeze(), bins.squeeze())

        # If we swap the order of the points, the angle should no longer
        # matter.
        bond_vector = rowan.rotate(rowan.conjugate(quats), points2 - points)
        bins = ((bond_vector + max_width) * cells_per_unit_length /
                2).astype(int)

        pmft.compute(
            (box, points2),
            quats,
            points,
            neighbors={
                "mode": "nearest",
                "num_neighbors": 1
            },
        )
        npt.assert_array_equal(
            np.asarray(np.where(pmft.bin_counts)).squeeze(), bins.squeeze())
Exemple #24
0
    (-3, [0, 0, 1]),
    (2, [1, 0, 0]),
    (2, [np.cos(np.pi / 3), np.sin(np.pi / 3), 0]),
    (2, [-np.cos(np.pi / 3), np.sin(np.pi / 3), 0]),
]

# http://www-history.mcs.st-and.ac.uk/~john/geometry/Lectures/L10.html
# Generated by hand
# Some variables to clean up the icosohedral group
icodi = np.pi - np.arctan(2)  # the dihedral angle
picodi = -np.pi / 2 + np.arctan(2)  # pi/2 - the dihedral angle
# a face vector that will be used a lot
face1 = [np.cos(picodi), 0, -np.sin(picodi)]
# the vector to the crown edges
lat_edge = rowan.rotate(
    rowan.from_axis_angle(axes=[0, 1, 0], angles=icodi / 2), [0, 0, 1])
# the vector to the mid-latitude edges
crown_edge = rowan.rotate(
    rowan.from_axis_angle(axes=face1, angles=2 * 2 * np.pi / 5), lat_edge)
crown_vert = [-0.850651, 0.0, 1.11352]  # A vertex in the top pentagon
equi_vert = rowan.rotate(
    rowan.from_axis_angle(axes=face1, angles=1 * 2 * np.pi / 5), crown_vert)

icosohedral = [
    (1, [1, 0, 0]),
    # first face pair
    (5, [0, 0, 1]),
    (5 / 2, [0, 0, 1]),
    (5 / 3, [0, 0, 1]),
    (5 / 4, [0, 0, 1]),
    # second face pair
Exemple #25
0
omega = np.radians(np.arange(0,365,5))

ro_y = {}
yi = 0

for v in tqdm(pf_xyz):
    
    ro_h = {}
    
    for fi,fam in enumerate(pf.symHKL):
        
        axis = np.cross(fam,v)
        angle = np.arccos(np.dot(fam,v))
        
        q0 = rowan.from_axis_angle(axis, angle)
        q0_n = rowan.normalize(q0) 
        
        q1_n = [rowan.normalize(rowan.from_axis_angle(h, omega)) for h in fam]
        
         # eu = np.zeros((len(omega),3,fam.shape[0]))
        eu = []
        
        for i,(qA,qB) in enumerate(zip(q0_n,q1_n)):
            
            qF = rowan.multiply(qA, qB)
            
            with np.errstate(divide='ignore'):

                temp = np.array((qF[:,1]/qF[:,0],qF[:,2]/qF[:,0],qF[:,3]/qF[:,0])).T
                ax = ro2ax(temp)
Exemple #26
0
def initialize(job):
    import hoomd
    import hoomd.hpmc
    import scipy.spatial
    """Sets up the system and sets default values for writers and stuf

    """
    # get sp params
    f = job.sp.patch_offset
    n_e = job.sp.n_edges
    n_ge = job.sp.n_guest_edges
    gar = job.sp.guest_aspect_ratio
    host_guest_area_ratio = job.sp.host_guest_area_ratio
    n_repeats = job.sp.n_repeats
    seed = job.sp.replica

    # initialize the hoomd context
    msg_fn = job.fn('init-hoomd.log')
    hoomd.context.initialize('--mode=cpu --msg-file={}'.format(msg_fn))

    # figure out shape vertices and patch locations
    xs = np.array([np.cos(n * 2 * np.pi / n_e) for n in range(n_e)])
    ys = np.array([np.sin(n * 2 * np.pi / n_e) for n in range(n_e)])
    zs = np.zeros_like(ys)
    vertices = np.vstack((xs, ys, zs)).T
    A_particle = scipy.spatial.ConvexHull(vertices[:, :2]).volume
    vertices = vertices - np.mean(vertices, axis=0)
    vertex_vertex_vectors = np.roll(vertices, -1, axis=0) - vertices
    half_edge_locations = vertices + 0.5 * vertex_vertex_vectors
    patch_locations = half_edge_locations + f * (vertices -
                                                 half_edge_locations)

    # make the guest particles
    xs = np.array([np.cos(n * 2 * np.pi / n_ge) for n in range(n_ge)])
    ys = np.array([np.sin(n * 2 * np.pi / n_ge) for n in range(n_ge)])
    zs = np.zeros_like(ys)
    guest_vertices = np.vstack((xs, ys, zs)).T
    rot_quat = rowan.from_axis_angle([0, 0, 1], 2 * np.pi / n_ge / 2)
    guest_vertices = rowan.rotate(rot_quat, guest_vertices)
    guest_vertices[:, 0] *= gar
    target_guest_area = A_particle * host_guest_area_ratio
    current_guest_area = scipy.spatial.ConvexHull(guest_vertices[:, :2]).volume
    guest_vertices *= np.sqrt(target_guest_area / current_guest_area)

    # save everything into the job doc that we need to
    if hoomd.comm.get_rank() == 0:
        job.doc.vertices = vertices
        job.doc.patch_locations = patch_locations
        job.doc.A_particle = A_particle
        job.doc.guest_vertices = guest_vertices
    hoomd.comm.barrier()

    # build the system
    if job.sp.initial_config in ('open', 's3'):
        uc = job._project.s3_unitcell(job.sp.patch_offset)
        system = hoomd.init.create_lattice(uc, n_repeats)
    else:
        raise NotImplementedError('Initialization not implemented.')

    # restart writer; period=None since we'll just call write_restart() at end
    restart_writer = hoomd.dump.gsd(filename=job.fn('restart.gsd'),
                                    group=hoomd.group.all(),
                                    truncate=True,
                                    period=None,
                                    phase=0)

    # set up the integrator with the shape info
    mc = hoomd.hpmc.integrate.convex_polygon(seed=seed, d=0, a=0)
    mc.shape_param.set('A', vertices=vertices[:, :2])
    total_particle_area = len(system.particles) * A_particle
    phi = total_particle_area / system.box.get_volume()
    sf = np.sqrt(phi / job.sp.phi)
    hoomd.update.box_resize(
        Lx=system.box.Lx * sf,
        Ly=system.box.Ly * sf,
        period=None,
    )
    restart_writer.dump_shape(mc)
    restart_writer.dump_state(mc)
    mc.set_params(d=0.1, a=0.5)

    # save everything into the job doc that we need to
    if hoomd.comm.get_rank() == 0:
        job.doc.mc_d = {x: 0.05 for x in system.particles.types}
        job.doc.mc_a = {x: 0.1 for x in system.particles.types}
        job.doc.vertices = vertices
        job.doc.patch_locations = patch_locations
        job.doc.A_particle = A_particle
        for k, v in job._project.required_defaults:
            job.doc.setdefault(k, v)
        os.system('cp {} {}'.format(job.fn('restart.gsd'), job.fn('init.gsd')))
    hoomd.comm.barrier()
    restart_writer.write_restart()
    if hoomd.comm.get_rank() == 0:
        os.system('cp {} {}'.format(job.fn('restart.gsd'), job.fn('init.gsd')))
    hoomd.comm.barrier()
    return
Exemple #27
0
    fibre_e[fi] = {}
    fibre_q[fi] = {}

    nn_gridPts[fi] = {}
    nn_gridDist[fi] = {}

    for yi in trange(len(xyz_pf)):

        y = xyz_pf[yi]

        #    for fi,fam in enumerate(pf.symHKL):

        axis = np.cross(fam, y)
        angle = np.arccos(np.dot(fam, y))

        q0 = quat.from_axis_angle(axis, angle)
        q0_n = quat.normalize(q0)

        q1_n = [quat.normalize(quat.from_axis_angle(h, omega)) for h in fam]

        # eu = np.zeros((len(omega),3,fam.shape[0]))
        eu2 = []

        qfib = np.zeros((len(q1_n[0]), len(q0_n), 4))

        for sym_eq, (qA, qB) in enumerate(zip(q0_n, q1_n)):

            temp = quat.multiply(qA, qB)

            qfib[:, sym_eq, :] = temp
Exemple #28
0
def calcFibre(symHKL, yset, qgrid, omega, rad, tree, euc_rad):

    fibre_e = {}
    fibre_q = {}

    nn_gridPts = {}
    nn_gridDist = {}

    egrid_trun = {}

    for fi, fam in enumerate(tqdm(symHKL)):

        fibre_e[fi] = {}
        fibre_q[fi] = {}

        nn_gridPts[fi] = {}
        nn_gridDist[fi] = {}

        egrid_trun[fi] = {}
        """ set proper iterator """
        if isinstance(yset, dict): it = yset[fi]
        else: it = yset

        q1_n = [quat.from_axis_angle(h, omega) for h in fam]

        for yi, y in enumerate(it):

            axis = np.cross(fam, y)
            angle = np.arccos(np.dot(fam, y))

            q0_n = quat.from_axis_angle(axis, angle)
            # q0_n = quat.normalize(q0)

            qfib = np.zeros((len(q1_n[0]), len(q0_n), 4))

            for sym_eq, (qA, qB) in enumerate(zip(q0_n, q1_n)):

                temp = quat.multiply(qA, qB)

                qfib[:, sym_eq, :] = temp

            phi1, Phi, phi2 = quat2eu(qfib)

            phi1 = np.where(phi1 < 0, phi1 + 2 * np.pi,
                            phi1)  #brnng back to 0 - 2pi
            Phi = np.where(Phi < 0, Phi + np.pi, Phi)  #brnng back to 0 - pi
            phi2 = np.where(phi2 < 0, phi2 + 2 * np.pi,
                            phi2)  #brnng back to 0 - 2pi

            eu_fib = np.stack((phi1, Phi, phi2), axis=2)
            eu_fib = np.reshape(eu_fib, (eu_fib.shape[0] * eu_fib.shape[1],
                                         eu_fib.shape[2]))  #new method

            fz = (eu_fib[:, 0] <= od._phi1max) & (
                eu_fib[:, 1] <= od._Phimax) & (eu_fib[:, 2] <= od._phi2max)
            fz_idx = np.nonzero(fz)

            fibre_e[fi][yi] = eu_fib[fz]

            fib_idx = np.unravel_index(fz_idx[0],
                                       (qfib.shape[0], qfib.shape[1]))

            fibre_q[fi][yi] = qfib[fib_idx]

            # """ reduce geodesic query size """
            # qfib_pos = np.copy(qfib[fib_idx])
            # qfib_pos[qfib_pos[:,0] < 0] *= -1

            # query = np.concatenate(tree.query_radius(qfib_pos,euc_rad))
            # query_uni = np.unique(query)
            # qgrid_trun = qgrid[query_uni]
            # qgrid_trun_idx = np.arange(len(qgrid))[query_uni] #store indexes to retrieve original grid pts later
            """ distance calc """
            temp = quatMetricNumba(qgrid, qfib[fib_idx])
            """ find tube """
            tube = (temp <= rad)
            temp = np.column_stack((np.argwhere(tube)[:, 0], temp[tube]))
            """ round very small values """
            temp = np.round(temp, decimals=7)
            """ move values at zero to very small (1E-5) """
            temp[:, 1] = np.where(temp[:, 1] == 0, 1E-5, temp[:, 1])
            """ sort by min distance """
            temp = temp[np.argsort(temp[:, 1], axis=0)]
            """ return unique pts (first in list) """
            uni_pts = np.unique(temp[:, 0], return_index=True)

            nn_gridPts[fi][yi] = uni_pts[0].astype(int)
            nn_gridDist[fi][yi] = temp[uni_pts[1], 1]

            # egrid_trun[fi][yi] = bungeAngs[query_uni]

    return nn_gridPts, nn_gridDist, fibre_e
Exemple #29
0
def _calcFibreHDF5(hfam, yset, omega, qgrid, od, h5fname, h5gname):

    fibre_e = {}
    fibre_q = {}

    nn_gridPts = {}
    nn_gridDist = {}

    f = _h5.File(h5fname, 'r+')
    grp = f.create_group(h5gname)
    fib_grp = grp.create_group('fibre')
    dist_grp = grp.create_group('dist')

    for yi, y in enumerate(yset):

        axis = _np.cross(hfam, y)
        angle = _np.arccos(_np.dot(hfam, y))

        q0 = _quat.from_axis_angle(axis, angle)
        q1 = [_quat.from_axis_angle(h, omega) for h in hfam]

        qfib = _np.zeros((len(q1[0]), len(q0), 4))

        for sym_eq, (qA, qB) in enumerate(zip(q0, q1)):

            temp = _quat.multiply(qA, qB)
            qfib[:, sym_eq, :] = temp

        phi1, Phi, phi2 = _quat2eu(qfib)

        phi1 = _np.where(phi1 < 0, phi1 + 2 * _np.pi,
                         phi1)  #brnng back to 0 - 2pi
        Phi = _np.where(Phi < 0, Phi + _np.pi, Phi)  #brnng back to 0 - pi
        phi2 = _np.where(phi2 < 0, phi2 + 2 * _np.pi,
                         phi2)  #brnng back to 0 - 2pi

        eu_fib = _np.stack((phi1, Phi, phi2), axis=2)
        eu_fib = _np.reshape(
            eu_fib,
            (eu_fib.shape[0] * eu_fib.shape[1], eu_fib.shape[2]))  #new method

        fz = (eu_fib[:, 0] < od._phi1max) & (eu_fib[:, 1] < od._Phimax) & (
            eu_fib[:, 2] < od._phi2max)
        fz_idx = _np.nonzero(fz)

        fibre_e[yi] = eu_fib[fz]

        fib_idx = _np.unravel_index(fz_idx[0], (qfib.shape[0], qfib.shape[1]))

        fibre_q[yi] = qfib[fib_idx]
        """ distance calc """
        temp = quatMetricNumba(qgrid, qfib[fib_idx])

        fib_grp.create_dataset(str(yi),
                               data=fibre_q[yi],
                               compression="gzip",
                               compression_opts=9)
        dist_grp.create_dataset(str(yi),
                                data=temp,
                                compression="gzip",
                                compression_opts=9)

        # """ find tube """
        # tube = (temp <= rad)
        # temp = _np.column_stack((_np.argwhere(tube)[:,0],temp[tube]))

        # """ round very small values """
        # temp = _np.round(temp, decimals=7)

        # """ move values at zero to very small (1E-5) """
        # temp[:,1] = _np.where(temp[:,1] == 0, 1E-5, temp[:,1])

        # """ sort by min distance """
        # temp = temp[_np.argsort(temp[:,1],axis=0)]
        # """ return unique pts (first in list) """
        # uni_pts = _np.unique(temp[:,0],return_index=True)

        # nn_gridPts[yi] = uni_pts[0]
        # nn_gridDist[yi] = temp[uni_pts[1],1]

    # return nn_gridPts, nn_gridDist, fibre_e, fibre_q
    f.close()
    return
Exemple #30
0
    azi = np.linspace(0,2*pi,azi_n)
    pol = np.ones((len(azi)))*pol

    x = np.sin(pol) * np.cos(azi)
    y = np.sin(pol) * np.sin(azi)
    z = np.cos(pol)

    pts.append(np.array((x,y,z)).T)

xyz_sphere = np.vstack(pts)

# %%

## secondary rotations
# offset_rots = quat.from_euler(np.deg2rad([0,0,0,0,0]), np.deg2rad([0,2,2,2,2]), np.deg2rad([0,5,10,15,20]),convention='zxz',axis_type='intrinsic')
offset_rots = quat.from_axis_angle(np.array(([-1,1,0],[-1,1,0],[1,-1,0],[-1,-1,2])), np.deg2rad([0,8,8,-8]))


cphi = np.cos(phi/2)
sphi = np.sin(phi/2)

q0 = {}
q = {}
qf = {}

fibre_e = {}
fibre_q = {}
tube_e = {}

nn_gridPts = {}
nn_gridDist = {}