예제 #1
0
    def test_broadcast(self):
        """Test broadcasting."""
        vec1 = np.array([1, 0, 0])
        vec2 = np.array([0, 1, 0])
        vec3 = np.array([0, 0, 1])

        arr1 = np.stack((vec2, vec3), axis=0)

        output = np.array([
            [0, np.sqrt(2) / 2, np.sqrt(2) / 2, 0],
            [0, np.sqrt(2) / 2, 0, np.sqrt(2) / 2],
        ])

        # Test both directions of single array broadcasting
        quat = rowan.vector_vector_rotation(vec1, arr1)
        self.assertTrue(np.allclose(quat, output))

        quat = rowan.vector_vector_rotation(arr1, vec1)
        self.assertTrue(np.allclose(quat, output))

        # Matching sizes
        arr2 = np.stack((vec1, vec1), axis=0)
        quat = rowan.vector_vector_rotation(arr1, arr2)
        self.assertTrue(np.allclose(quat, output))

        # Proper broadcasting
        arr1 = np.stack((vec2, vec3), axis=0)[:, np.newaxis, ...]
        arr2 = np.stack((vec1, vec1), axis=0)[np.newaxis, ...]
        bcast_output = output[:, np.newaxis, ...].repeat(2, axis=1)

        quat = rowan.vector_vector_rotation(arr1, arr2)
        self.assertTrue(np.allclose(quat, bcast_output))
예제 #2
0
    def test_ap(self):
        """Test finding quaternion to rotate antiparallel vectors onto each other."""
        # For this test, there are multiple quaternions that would effect the
        # correct rotation, so rather than checking for a specific one we check
        # that the appropriate rotation results from applying the quaternion
        vec1 = np.array([1, 0, 0])
        vec2 = np.array([0, 1, 0])
        quat = rowan.vector_vector_rotation(vec1, vec2)
        self.assertTrue(
            np.allclose(rowan.rotate(quat, vec1),
                        vec2 / np.linalg.norm(vec2, axis=-1)))

        vec1 = np.array([1, 0, 0])
        vec2 = np.array([[0, 1, 0], [2, 0, 0], [-2, 0, 0]])
        quat = rowan.vector_vector_rotation(vec1, vec2)
        self.assertTrue(
            np.allclose(
                rowan.rotate(quat, vec1),
                vec2 / np.linalg.norm(vec2, axis=-1)[:, np.newaxis],
            ))

        vec1 = np.array([0, 1, 0])
        vec2 = np.array([[0, 0, 1], [0, 2, 0], [0, -2, 0]])
        quat = rowan.vector_vector_rotation(vec1, vec2)
        self.assertTrue(
            np.allclose(
                rowan.rotate(quat, vec1),
                vec2 / np.linalg.norm(vec2, axis=-1)[:, np.newaxis],
            ))
예제 #3
0
 def test_simple(self):
     """Test finding quaternion to rotate a vector onto another vector."""
     vec1 = np.array([1, 0, 0])
     vec2 = np.array([0, 1, 0])
     vec3 = np.array([0, 0, 1])
     quat = rowan.vector_vector_rotation(vec1, vec2)
     self.assertTrue(
         np.allclose(quat, np.array([[0,
                                      np.sqrt(2) / 2,
                                      np.sqrt(2) / 2, 0]])))
     quat = rowan.vector_vector_rotation(vec1, vec3)
     self.assertTrue(
         np.allclose(quat, np.array([[0,
                                      np.sqrt(2) / 2, 0,
                                      np.sqrt(2) / 2]])))
예제 #4
0
def field_scene(N=10, use='ellipsoids'):
    features = dict(ambient_light=.4)
    (positions, units) = example_vector_field(5)

    normalized_z = positions[:, 2].copy()
    normalized_z -= np.min(normalized_z)
    normalized_z /= np.max(normalized_z)

    colors = plato.cmap.cubehelix(normalized_z, h=1.4)
    colors[:, :3] = .5 * (colors[:, :3] + plato.cmap.cubeellipse(
        np.arctan2(positions[:, 1], positions[:, 0])))

    if use == 'ellipsoids':
        orientations = rowan.vector_vector_rotation([(1, 0, 0)], units)
        prim = draw.Ellipsoids(positions=positions,
                               orientations=orientations,
                               colors=colors,
                               a=.5,
                               b=.125,
                               c=.125)
    elif use == 'lines':
        features['ambient_light'] = 1
        starts = positions - units / 2
        ends = positions + units / 2

        prim = draw.Lines(start_points=starts,
                          end_points=ends,
                          colors=colors,
                          widths=np.ones(len(positions)) * .25)
    else:
        raise NotImplementedError('Unknown primitive {}'.format(use))

    rotation = [0.8126942, 0.35465172, -0.43531808, 0.15571932]
    scene = draw.Scene(prim, zoom=4, features=features, rotation=rotation)
    return scene
예제 #5
0
def get_quaternions(n_views=20):
    """Get the quaternions for the specified number of views.

    The first (n_view - 3) views will be the views even distributed on a sphere,
    while the last three views will be the face-on, edge-on, and corner-on
    views, respectively.

    These quaternions are useful as input to `view_orientation` kwarg in
    `freud.diffraction.Diffractometer.compute`.

    Parameters
    ----------
    n_views : int, default 20
        The number of views to compute.

    Returns
    -------
    list of numpy.ndarray
        Quaternions as (4,) arrays.
    """
    if n_views <= 3 or not isinstance(n_views, int):
        raise ValueError("Please set n_views to an integer greater than 3.")
    # Calculate points for even distribution on a sphere
    ga = np.pi * (3 - 5**0.5)
    theta = ga * np.arange(n_views - 3)
    z = np.linspace(1 - 1 / (n_views - 3), 1 / (n_views - 3), n_views - 3)
    radius = np.sqrt(1 - z * z)
    points = np.zeros((n_views, 3))
    points[:-3, 0] = radius * np.cos(theta)
    points[:-3, 1] = radius * np.sin(theta)
    points[:-3, 2] = z

    # face on
    points[-3] = np.array([0, 0, 1])
    # edge on
    points[-2] = np.array([0, 1, 1])
    # corner on
    points[-1] = np.array([1, 1, 1])

    unit_z = np.array([0, 0, 1])
    return [vector_vector_rotation(i, unit_z) for i in points]
예제 #6
0
파일: Lines.py 프로젝트: mkhorton/plato
    def update_arrays(self):
        if not self._dirty_attributes:
            return

        # TODO make number of facets a configurable attribute
        thetas = np.linspace(0, 2 * np.pi, 10, endpoint=False)

        # to begin, pretend we are constructing a unit circle in the
        # xy plane; multiply xy by each line radius and z by each line
        # length before rotating and translating appropriately
        image = np.array(
            [np.cos(thetas),
             np.sin(thetas),
             np.zeros_like(thetas)]).T
        image = np.concatenate([image, image + (0, 0, 1)], axis=0)

        # indices to make all triangles for a given Line object
        image_indices = np.tile(
            np.arange(2 * len(thetas))[:, np.newaxis], (1, 3))
        image_indices[:len(thetas), 1] += 1
        image_indices[:len(thetas), 2] += len(thetas)
        image_indices[len(thetas):, 1] += 1 - len(thetas)
        image_indices[len(thetas):, 2] += 1
        image_indices[len(thetas) - 1, 1] -= len(thetas)
        image_indices[-1, 1:] -= len(thetas)

        cap_indices = np.array(
            list(
                geometry.fanTriangleIndices(
                    np.arange(len(thetas))[np.newaxis])))
        image_indices = np.concatenate(
            [image_indices, cap_indices[:, ::-1],
             len(thetas) + cap_indices],
            axis=0)

        # normal vectors for each Line segment
        normals = self.end_points - self.start_points
        lengths = np.linalg.norm(normals, axis=-1, keepdims=True)
        normals /= lengths

        # find quaternion to rotate (0, 0, 1) into the direction each
        # Line is pointing
        quats = rowan.vector_vector_rotation(
            np.array([0, 0, 1.])[np.newaxis, :], normals)

        # Nlines*Nvertices*3
        vertices = np.tile(image[np.newaxis], (len(quats), 1, 1))
        # set xy according to line width
        vertices[:, :, :2] *= self.widths[:, np.newaxis, np.newaxis] * 0.5
        # set z according to line length
        vertices[:, :, 2] *= lengths[:, np.newaxis, 0]
        # rotate appropriately
        vertices = rowan.rotate(quats[:, np.newaxis], vertices)
        # translation by start_points will happen in _finalize_primitive_arrays

        # these are incorrect normals, but this looks to be the most
        # straightforward way to have the normals get serialized
        normals = vertices - self.start_points[:, np.newaxis]

        colors = np.tile(self.colors[:, np.newaxis], (1, len(image), 1))

        positions = np.tile(self.start_points[:, np.newaxis],
                            (1, len(image), 1))

        self._finalize_primitive_arrays(positions, None, colors, vertices,
                                        normals, image_indices)