Ejemplo n.º 1
0
    def test_barycentric(self):
        #2d test
        simplex1 = np.array([[0.3, 0.1], [0.2, -1.2], [1.3, 2.3]])
        pts1 = np.array([[0.6, 0.1], [1.3, 2.3], [0.5, 0.5], [.7, 1]])
        output1 = barycentric_coords(pts1, simplex1)
        #do back conversion to cartesian
        o_dot_s = np.sum(output1[:, :, None] * simplex1[None, :, :], axis=1)
        self.assertTrue(np.allclose(pts1, o_dot_s))

        #do 3d tests
        simplex2 = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 0]])
        pts2 = np.array([[0, 0, 1], [0, 0.5, 0.5], [1./3, 1./3, 1./3]])
        output2 = barycentric_coords(pts2, simplex2)
        self.assertTrue(np.allclose(output2[1], [0.5, 0.5, 0, 0]))
        #do back conversion to cartesian
        o_dot_s = np.sum(output2[:, :, None] * simplex2[None, :, :], axis=1)
        self.assertTrue(np.allclose(pts2, o_dot_s))
        #test single point
        self.assertTrue(np.allclose(output2[2],
                                    barycentric_coords(pts2[2], simplex2)))
    def _voronoi_points(self, structure):
        """
        returns the voronoi points for a structure. returns in the 
        format of a list of lists, where the first index corresponds
        to the index of the site in the original structure that neighbors
        the point. I.e. simplices[0] is the list of points around the site
        structure[0]
        """
        all_coords = self._fake_periodic(structure)
        logging.debug("Starting calculating Voronoi points")
        vt = VoronoiTess(all_coords)
        simplices = []
        # only return the coordinates associated with the
        # points in the original structure
        for i, r in enumerate(vt.regions[: len(structure)]):
            points = []
            for v in r:
                if self._interior:
                    new_site = PeriodicSite("X", vt.vertices[v], structure.lattice, coords_are_cartesian=True)
                    d = structure[i].distance(new_site)
                    s_points = structure.get_neighbors_in_shell(new_site.coords, d, 0.01)
                    s_points = map(lambda x: x[0].coords, s_points)
                    # brute force check that point is in its polyhedron
                    # (len(s_points) should usually be 4, except in high
                    # symmetry cases)
                    for simplex in itertools.combinations(s_points, 4):
                        try:
                            bcs = barycentric_coords(vt.vertices[v], np.array(simplex))
                            if np.min(bcs) > 0:
                                points.append(vt.vertices[v])
                                break
                        except np.linalg.LinAlgError as err:
                            if "Singular matrix" not in err.message:
                                raise

                else:
                    points.append(vt.vertices[v])
            simplices.append(points)
        logging.debug("Finished calculating Voronoi points")
        return simplices