示例#1
0
    def bounding_circle(self):
        """tuple[float, float]: Get the center and radius of the bounding circle."""  # noqa: E501
        if not MINIBALL:
            raise ImportError("The miniball module must be installed. It can "
                              "be installed as an extra with coxeter (e.g. "
                              "with pip install coxeter[bounding_sphere], or "
                              "directly from PyPI using pip install miniball.")

        # The algorithm in miniball involves solving a linear system and
        # can therefore occasionally be somewhat unstable. Applying a
        # random rotation will usually fix the issue.
        max_attempts = 10
        attempt = 0
        current_rotation = [1, 0, 0, 0]
        vertices = self.vertices
        while attempt < max_attempts:
            attempt += 1
            try:
                center, r2 = miniball.get_bounding_ball(vertices)
                break
            except np.linalg.LinAlgError:
                current_rotation = rowan.random.rand(1)
                vertices = rowan.rotate(current_rotation, vertices)

        if attempt == max_attempts:
            raise RuntimeError("Unable to solve for a bounding sphere.")

        # The center must be rotated back to undo any rotation.
        center = rowan.rotate(rowan.conjugate(current_rotation), center)

        return Circle(np.sqrt(r2), center)
示例#2
0
    def minimal_bounding_sphere(self):
        """:class:`~.Sphere`: Get the polyhedron's bounding sphere."""
        if not MINIBALL:
            raise ImportError(
                "The miniball module must be installed. It can "
                "be installed as an extra with coxeter (e.g. "
                'with "pip install coxeter[bounding_sphere]") or '
                'directly from PyPI using "pip install miniball".'
            )

        # The algorithm in miniball involves solving a linear system and
        # can therefore occasionally be somewhat unstable. Applying a
        # random rotation will usually fix the issue.
        max_attempts = 10
        attempt = 0
        current_rotation = [1, 0, 0, 0]
        vertices = self.vertices
        while attempt < max_attempts:
            attempt += 1
            try:
                center, r2 = miniball.get_bounding_ball(vertices)
                break
            except np.linalg.LinAlgError:
                current_rotation = rowan.random.rand(1)
                vertices = rowan.rotate(current_rotation, vertices)
        else:
            raise RuntimeError("Unable to solve for a bounding sphere.")

        # The center must be rotated back to undo any rotation.
        center = rowan.rotate(rowan.conjugate(current_rotation), center)

        return Sphere(np.sqrt(r2), center)
def return_correlation(l, initial_q, orientations):
    """Compute the rotational autocorrelation."""
    calc_quats = rowan.multiply(rowan.conjugate(initial_q), orientations)
    ref_quats = rowan.multiply(rowan.conjugate(initial_q), initial_q)

    ref_angles = quat_to_greek(ref_quats)
    calc_angles = quat_to_greek(calc_quats)

    f_of_t = 0

    for m1 in np.arange(-l / 2, l / 2 + 1):
        for m2 in np.arange(-l / 2, l / 2 + 1):
            ref_y = hypersphere_harmonic(ref_angles, l, m1, m2)
            calc_y = hypersphere_harmonic(calc_angles, l, m1, m2)
            f_of_t += (ref_y.conjugate() * calc_y)

    return f_of_t.real
示例#4
0
    def get_bin(self, query_point, point, query_point_orientation,
                point_orientation):
        r_ij = point - query_point
        rot_r_ij = rowan.rotate(rowan.conjugate(query_point_orientation), r_ij)

        limits = np.asarray(self.limits)
        return tuple(
            np.floor((rot_r_ij[:2] + limits) * np.asarray(self.bins) /
                     (2 * limits)).astype(np.int32))
示例#5
0
 def test_conjugate(self):
     """Test quaternion conjugation."""
     np.random.seed(0)
     shapes = [(4,), (5, 4), (5, 5, 4), (5, 5, 5, 4)]
     for shape in shapes:
         quats = np.random.random_sample(shape)
         quats_conj = quats.copy()
         quats_conj[..., 1:] *= -1
         self.assertTrue(np.all(rowan.conjugate(quats) == quats_conj))
示例#6
0
文件: Scene.py 项目: mkhorton/plato
    def rotation(self, value):
        camera = self._backend_objects['camera']

        # rotating a scene by q is equivalent to rotating the camera's
        # position and up vector by q*
        conj = rowan.conjugate(value)
        camera_distance = np.linalg.norm(camera.position)

        camera.position = rowan.rotate(conj, [0, 0, camera_distance]).tolist()
        camera.up = rowan.rotate(conj, [0, 1, 0]).tolist()

        self._backend_objects['controls'].exec_three_obj_method('update')
示例#7
0
文件: Scene.py 项目: mkhorton/plato
 def rotation(self):
     camera = self._backend_objects['camera']
     norm_out = np.array(camera.position)
     norm_out /= np.linalg.norm(norm_out)
     norm_up = np.array(camera.up)
     norm_up -= np.dot(norm_up, norm_out) * norm_out
     norm_up /= np.linalg.norm(norm_up)
     norm_right = np.cross(norm_up, norm_out)
     rotation_matrix = np.array([norm_right, norm_up, norm_out]).T
     result = rowan.from_matrix(rotation_matrix, require_orthogonal=False)
     result = rowan.conjugate(result)
     return result
示例#8
0
    def get_bin(self, query_point, point, query_point_orientation,
                point_orientation):
        r_ij = point - query_point
        rot_r_ij = rowan.rotate(rowan.conjugate(query_point_orientation), r_ij)

        limits = np.asarray(self.limits)
        xy_bins = tuple(
            np.floor((rot_r_ij[:2] + limits) * np.asarray(self.bins[:2]) /
                     (2 * limits)).astype(np.int32))

        point_angle = rowan.geometry.angle(point_orientation)
        angle_bin = np.floor(
            ((point_angle - np.arctan2(-r_ij[1], -r_ij[0])) % TWO_PI) *
            self.bins[2] / TWO_PI).astype(np.int32)
        return xy_bins + (angle_bin, )
示例#9
0
    def test_slerp_prime(self):
        """Test spherical linear interpolation derivative."""
        self.assertTrue(np.all(interpolate.slerp_prime(one, one, 0) == zero))
        self.assertTrue(np.all(interpolate.slerp_prime(one, one, 1) == zero))
        self.assertTrue(np.all(interpolate.slerp_prime(one, one, 0.5) == zero))

        self.assertTrue(
            np.allclose(
                interpolate.slerp_prime(root_two, one, 0.5),
                rowan.multiply(
                    interpolate.slerp(root_two, one, 0.5),
                    rowan.log(rowan.multiply(rowan.conjugate(root_two), one)),
                ),
            )
        )
示例#10
0
文件: Scene.py 项目: mkhorton/plato
    def _update_camera(self):
        camera = self._backend_objects['camera']
        (width, height) = self.size.astype(np.float32)

        dz = np.sqrt(np.sum(self.size**2)) * self._clip_scale

        conj = rowan.conjugate(self.rotation)

        translation = rowan.rotate(conj, [0, 0, 1 + dz / 2])

        camera.left = -width / 2
        camera.right = width / 2
        camera.top = height / 2
        camera.bottom = -height / 2
        camera.far = 1 + dz
        camera.up = rowan.rotate(conj, (0, 1, 0)).tolist()
        camera.position = translation.tolist()
示例#11
0
def compute_rotational_ke(snapshot: Snapshot) -> float:
    """Compute the kinetic energy of the rotational degrees of freedom.

    Args:
        snapshot: (Snapshot): Simulation snapshot from which to compute the kinetic energy

    Returns: The total rotational kinetic energy of the snapshot.

    """
    num_mols = get_num_mols(snapshot)
    angmom = snapshot.particles.angmom[:num_mols]
    moment_inertia = snapshot.particles.moment_inertia[:num_mols]
    momentum = rowan.multiply(
        0.5 * rowan.conjugate(snapshot.particles.orientation[:num_mols]), angmom
    )[:, 1:]
    mask = moment_inertia > 0
    return np.sum(0.5 * np.square(momentum[mask]) / moment_inertia[mask])
示例#12
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)
示例#13
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())
示例#14
0
文件: Scene.py 项目: mkhorton/plato
 def translation(self, value):
     controls = self._backend_objects['controls']
     value = np.asarray(value) - (0, 0, self.z_offset)
     value = rowan.rotate(rowan.conjugate(self.rotation), value)
     controls.target = (-value).tolist()
     controls.exec_three_obj_method('update')
示例#15
0
文件: Scene.py 项目: glotzerlab/plato
    def render(self):
        """Render this Scene object."""
        # Remove existing fresnel geometries from the scene
        for geometry in self._geometries:
            geometry.remove()

        # Clear the list of fresnel geometries
        self._geometries = []

        # Add fresnel scene geometries from plato scene primitives
        for prim in self._primitives:
            geometry = prim.render(self._fresnel_scene)
            self._geometries.append(geometry)

        # Set up the camera
        camera_up = rowan.rotate(rowan.conjugate(self.rotation), [0, 1, 0])
        camera_position = rowan.rotate(rowan.conjugate(self.rotation), -self.translation)
        camera_look_at = camera_position + rowan.rotate(rowan.conjugate(self.rotation), [0, 0, -1])
        camera_height = self.size[1]/self.zoom
        try:
            orthographic_camera = fresnel.camera.Orthographic
        except AttributeError:
            # Support fresnel < 0.13.0
            orthographic_camera = fresnel.camera.orthographic
        self._fresnel_scene.camera = orthographic_camera(
            position=camera_position,
            look_at=camera_look_at,
            up=camera_up,
            height=camera_height)

        # Set up lights
        lights = []
        if 'ambient_light' in self.enabled_features:
            config = self.get_feature_config('ambient_light')
            magnitude = config.get('value', 0.25)
            if magnitude > 0:
                lights.append(fresnel.light.Light(direction=(0, 0, 1),
                                                  color=(magnitude, magnitude, magnitude),
                                                  theta=np.pi))
        if 'directional_light' in self.enabled_features:
            config = self.get_feature_config('directional_light')
            directions = config.get('value', (.25, .5, -1))
            directions = np.atleast_2d(directions).astype(np.float32)
            for direction in directions:
                magnitude = np.linalg.norm(direction)
                if magnitude > 0:
                    lights.append(fresnel.light.Light(direction=-direction,
                                                      color=(magnitude, magnitude, magnitude),
                                                      theta=0.7))
        if len(lights) > 0:
            self._fresnel_scene.lights = lights

        # Set up tracer
        if 'pathtracer' in self.enabled_features:
            # Use path tracer if enabled
            config = self.get_feature_config('pathtracer')
            tracer = self._path_tracer
            samples = config.get('samples', 64)
            def render_function(scene, **kwargs):
                return tracer.sample(scene, samples, **kwargs)
        else:
            # Use preview tracer by default
            tracer = self._preview_tracer
            tracer.anti_alias = 'antialiasing' in self.enabled_features
            render_function = tracer.render

        self._output = render_function(self._fresnel_scene)
示例#16
0
文件: math.py 项目: hillarypan/plato
def quatconj(q):
    """Returns the conjugate of a quaternion array q*"""
    return -rowan.conjugate(q)