Beispiel #1
0
    def test_geodesic_input(self, n, radius, center):
        U = Rotation.random(random_state=0).as_matrix()
        thetas = np.linspace(0, 2 * np.pi, n, endpoint=False)
        points = np.vstack([np.sin(thetas), np.cos(thetas), np.zeros(n)]).T
        points = radius * points @ U
        sv = SphericalVoronoi(points + center, radius=radius, center=center)

        # each region must have 4 vertices
        region_sizes = np.array([len(region) for region in sv.regions])
        assert (region_sizes == 4).all()
        regions = np.array(sv.regions)

        # vertices are those between each pair of input points + north and
        # south poles
        vertices = sv.vertices - center
        assert len(vertices) == n + 2

        # verify that north and south poles are orthogonal to geodesic on which
        # input points lie
        poles = vertices[n:]
        assert np.abs(np.dot(points, poles.T)).max() < 1E-10

        for point, region in zip(points, sv.regions):
            cosine = np.dot(vertices[region], point)
            sine = np.linalg.norm(np.cross(vertices[region], point), axis=1)
            arclengths = radius * np.arctan2(sine, cosine)
            # test arc lengths to poles
            assert_almost_equal(arclengths[[1, 3]], radius * np.pi / 2)
            # test arc lengths to forward and backward neighbors
            assert_almost_equal(arclengths[[0, 2]], radius * np.pi / n)

        regions = sv.regions.copy()
        sv.sort_vertices_of_regions()
        assert regions == sv.regions
Beispiel #2
0
    def __init__(self, refinement=2, vecs=None):
        """ Setup a triangular grid on the 2-sphere.

        Args:
            vecs : array of shape (3, l_labels)
            refinement : if vecs is None, the triangulation is generated using
                         trisphere(refinement), defined below
        """
        if vecs is None:
            vecs, tris = trisphere(refinement)
            vecs = normalize(vecs)
        else:
            assert (vecs.shape[0] == 3)
            vecs = normalize(vecs)
            sv = SphericalVoronoi(vecs.T)
            sv.sort_vertices_of_regions()
            tris = sv._tri.simplices.T
        assert (tris.shape[0] == 3)

        s_manifold = 2
        m_gradients = tris.shape[1]
        r_points = 3
        l_labels = vecs.shape[1]

        logging.info("Set up for 2-sphere with {l} labels and {m} gradients." \
            .format(s=s_manifold, l=l_labels,m=m_gradients))

        self.v = vecs
        self.faces = tris
        self.mdims = {
            's_manifold': s_manifold,
            'm_gradients': m_gradients,
            'r_points': r_points,
            'l_labels': l_labels
        }

        self.v_grad = np.zeros((3, m_gradients), order='C')
        for j in range(m_gradients):
            # v : columns correspond to the vertices of triangle j
            v = self.v[:, self.faces[:, j]]
            # v0 : centroid of triangle j
            # taking the mean is a bottle neck here!
            self.v_grad[:, j] = self.mean(v).ravel()

        # b { l_labels }
        # P { m_gradients, r_points }
        # b : vol. elements, s.t. sum(self.b) converges to 4*PI as n to inf
        self.b = np.zeros((l_labels, ), order='C')
        self.b[:] = sphere_areas(vecs)
        self.b_precond = 1.0 / np.sqrt(np.einsum('i,i->', self.b, self.b))
        self.P = np.zeros((m_gradients, r_points), order='C', dtype=np.int64)
        self.P[:] = tris.T

        # A { m_gradients, s_manifold, s_manifold }
        # B { m_gradients, s_manifold, r_points }
        self.A = np.zeros((m_gradients, s_manifold, s_manifold), order='C')
        self.B = np.zeros((m_gradients, s_manifold, r_points), order='C')

        self.setup_taylor_grad()
Beispiel #3
0
def get_dual2(g, points):
    sv = SphericalVoronoi(points)
    sv.sort_vertices_of_regions()
    faces = []
    for region in sv.regions:
        face = sv.vertices[region]
        faces.append(face)
    return np.array(faces)
Beispiel #4
0
 def iteration(pts):
     diagram = SphericalVoronoi(pts, radius=radius, center=np.array(center))
     diagram.sort_vertices_of_regions()
     centers = []
     for region in diagram.regions:
         verts = np.array([diagram.vertices[i] for i in region])
         new_vert = weighted_center(verts, weight_field)
         centers.append(tuple(new_vert))
     return centers
 def test_sort_vertices_of_regions_flattened(self):
     expected = sorted([[0, 6, 5, 2, 3], [2, 3, 10, 11, 8, 7], [0, 6, 4, 1], [4, 8,
         7, 5, 6], [9, 11, 10], [2, 7, 5], [1, 4, 8, 11, 9], [0, 3, 10, 9,
             1]])
     expected = list(itertools.chain(*sorted(expected)))
     sv = SphericalVoronoi(self.points)
     sv.sort_vertices_of_regions()
     actual = list(itertools.chain(*sorted(sv.regions)))
     assert_array_equal(actual, expected)
Beispiel #6
0
 def test_region_types(self):
     # Tests that region integer type does not change
     # See Issue #13412
     sv = SphericalVoronoi(self.points)
     dtype = type(sv.regions[0][0])
     sv.sort_vertices_of_regions()
     assert type(sv.regions[0][0]) == dtype
     sv.sort_vertices_of_regions()
     assert type(sv.regions[0][0]) == dtype
Beispiel #7
0
 def test_sort_vertices_of_regions_dimensionality(self):
     points = np.array([[1, 0, 0, 0],
                        [0, 1, 0, 0],
                        [0, 0, 1, 0],
                        [0, 0, 0, 1],
                        [0.5, 0.5, 0.5, 0.5]])
     with pytest.raises(TypeError, match="three-dimensional"):
         sv = SphericalVoronoi(points)
         sv.sort_vertices_of_regions()
Beispiel #8
0
 def test_sort_vertices_of_regions_flattened(self):
     expected = sorted([[0, 6, 5, 2, 3], [2, 3, 10, 11, 8, 7], [0, 6, 4, 1],
                        [4, 8, 7, 5, 6], [9, 11, 10], [2, 7, 5],
                        [1, 4, 8, 11, 9], [0, 3, 10, 9, 1]])
     expected = list(itertools.chain(*sorted(expected)))
     sv = SphericalVoronoi(self.points)
     sv.sort_vertices_of_regions()
     actual = list(itertools.chain(*sorted(sv.regions)))
     assert_array_equal(actual, expected)
Beispiel #9
0
    def plot_old(self, plot_points=False, mark_peaks=0):
        ''' Plot the points on the sphere with their values '''

        from scipy import rand
        import matplotlib.colors as colors
        #from mpl_toolkits.mplot3d import Axes3D
        import mpl_toolkits.mplot3d as a3
        import matplotlib.pyplot as plt

        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')

        if plot_points:
            ax.scatter(self.x, self.y, self.z, c='b', marker='o')

        if mark_peaks > 0:

            id = self.find_peaks(k=mark_peaks)
            s = 1.05
            ax.scatter(s*self.x[id], s*self.y[id], s*self.z[id], c='k', marker='o')

        voronoi = SphericalVoronoi(self.cartesian.T)
        voronoi.sort_vertices_of_regions()

        if self.values is not None:

            col_max = self.values.max()
            col_min = self.values.min()

            if col_min != col_max:
                col_map = (self.values - col_min) / (col_max - col_min)
            else:
                col_map = self.values / col_max

        else:

            col_map = np.zeros(self.n_points)

        cmap = plt.get_cmap('coolwarm')

        # plot the walls
        for v_ind, col in zip(voronoi.regions, col_map):
            triangle = a3.art3d.Poly3DCollection([voronoi.vertices[v_ind]], alpha=1., linewidth=0.0)
            triangle.set_color(cmap(col))
            triangle.set_edgecolor('k')
            ax.add_collection3d(triangle)

        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        ax.set_zlabel('Z')
        ax.set_xlim([-1,1])
        ax.set_ylim([-1,1])
        ax.set_zlim([-1,1])
Beispiel #10
0
    def test_circular_input(self, n, radius, fraction, center):
        # generate a random circle
        rng = np.random.RandomState(0)
        U = Rotation.random(random_state=rng).as_matrix()
        h = radius * fraction
        circle_radius = np.sqrt(radius**2 - h**2)
        thetas = np.linspace(0, 2 * np.pi, n, endpoint=False)
        points = np.vstack([
            circle_radius * np.sin(thetas), circle_radius * np.cos(thetas),
            h * np.ones(n)
        ]).T
        points = points @ U

        # calculate Spherical Voronoi diagram
        sv = SphericalVoronoi(points + center, radius=radius, center=center)

        # each region must have 4 vertices
        region_sizes = np.array([len(region) for region in sv.regions])
        assert (region_sizes == 4).all()
        regions = np.array(sv.regions)

        # vertices are those between each pair of input points + north and
        # south poles
        vertices = sv.vertices - center
        assert len(vertices) == n + 2

        # verify that north and south poles are orthogonal to circle on which
        # input points lie
        poles = vertices[n:]
        midpoint = np.array([0, 0, h]) @ U
        assert np.abs(np.dot(points - midpoint, poles.T)).max() < 1E-10

        # test arc lengths to forward and backward neighbors
        for point, region in zip(points, sv.regions):
            cosine = np.dot(vertices[region] - midpoint, point - midpoint)
            sine = np.linalg.norm(np.cross(vertices[region] - midpoint,
                                           point - midpoint),
                                  axis=1)
            arclengths = circle_radius * np.arctan2(sine, cosine)
            assert_almost_equal(arclengths[[0, 2]], circle_radius * np.pi / n)

        # test arc lengths to poles
        for point, region in zip(points, sv.regions):
            cosine = np.dot(vertices[region], point)
            sine = np.linalg.norm(np.cross(vertices[region], point), axis=1)
            arclengths = np.arctan2(sine, cosine)
            angle = np.arcsin(h / radius)
            assert_almost_equal(arclengths[1], np.pi / 2 - angle)
            assert_almost_equal(arclengths[3], np.pi / 2 + angle)

        regions = sv.regions.copy()
        sv.sort_vertices_of_regions()
        assert regions == sv.regions
def voro3D(points=np.array([0, 0, 0]), center=np.array([0, 0, 0])):
    #~ center = np.array([np.mean(points), np.mean(points), np.mean(points)])

    radius = np.amax(points)
    #~ print "Center = %25.20f\t%25.20f\t%25.20f" % (center[0],center[1], center[2])
    #~ print "Radius = %25.20f" % radius
    #~ print points.shape
    # calculate spherical Voronoi diagram
    sv = SphericalVoronoi(points, radius, center)
    # sort vertices (optional, helpful for plotting)
    sv.sort_vertices_of_regions()
    return sv
Beispiel #12
0
class SphericalVorSort(Benchmark):
    params = [10, 100, 1000, 5000, 10000]
    param_names = ['num_points']

    def setup(self, num_points):
        self.points = generate_spherical_points(num_points)
        self.sv = SphericalVoronoi(self.points, radius=1, center=np.zeros(3))

    def time_spherical_polygon_vertex_sorting(self, num_points):
        """Time the vertex sorting operation in the Spherical Voronoi
        code.
        """
        self.sv.sort_vertices_of_regions()
Beispiel #13
0
class SphericalVorSort(Benchmark):
    params = [10, 100, 1000, 5000, 10000]
    param_names = ['num_points']

    def setup(self, num_points):
        self.points = generate_spherical_points(num_points)
        self.sv = SphericalVoronoi(self.points, radius=1,
                                   center=np.zeros(3))

    def time_spherical_polygon_vertex_sorting(self, num_points):
        """Time the vertex sorting operation in the Spherical Voronoi
        code.
        """
        self.sv.sort_vertices_of_regions()
Beispiel #14
0
def addVoronoi(points):
    """add voronoi on the surface. Note that before using this function, modify the parameters(radius, center) first"""
    radius = RADIUS
    points = points/radius
    center = np.array([0, 0, 0])
    sv = SphericalVoronoi(points, 1, center)
    sv.sort_vertices_of_regions()
    t_vals = np.linspace(0, 1, 2000)#set the num of points on the line
    result = np.random.rand(0, 2000, 3)
    for region in sv.regions:
        n = len(region)
        for i in range(n):
            start = sv.vertices[region][i]
            end = sv.vertices[region][(i + 1) % n]
            if not (start == end).all():
                temp=radius*geometric_slerp(start, end, t_vals)
                result = np.concatenate((result, temp[None]), axis=0)
    return result
Beispiel #15
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            vertices_s = self.inputs['Vertices'].sv_get()
            radius_s = self.inputs['Radius'].sv_get()
            center_s = self.inputs['Center'].sv_get()

            verts_out = []
            edges_out = []
            faces_out = []

            for sites, center, radius in zip_long_repeat(
                    vertices_s, center_s, radius_s):
                if isinstance(radius, (list, tuple)):
                    radius = radius[0]
                center = center[0]
                sites = np.array(
                    [project_to_sphere(center, radius, v) for v in sites])

                vor = SphericalVoronoi(sites,
                                       radius=radius,
                                       center=np.array(center))
                vor.sort_vertices_of_regions()

                new_verts = vor.vertices.tolist()
                new_faces = vor.regions
                #new_edges = polygons_to_edges([new_faces], True)[0]

                bm2 = bmesh_from_pydata(new_verts, [],
                                        new_faces,
                                        normal_update=True)
                bmesh.ops.recalc_face_normals(bm2, faces=bm2.faces)
                new_verts, new_edges, new_faces = pydata_from_bmesh(bm2)
                bm2.free()

                verts_out.append(new_verts)
                edges_out.append(new_edges)
                faces_out.append(new_faces)

            self.outputs['Vertices'].sv_set(verts_out)
            self.outputs['Edges'].sv_set(edges_out)
            self.outputs['Faces'].sv_set(faces_out)
Beispiel #16
0
def backbone_network(vstations, points, stns, ties):

    if isinstance(ties, list):
        # make a numpy array with the points if list passed
        ties = np.array(ties)

    flt = np.ones(len(ties), dtype=np.bool)

    # get xyz of the stations
    pc = ll2sphere_xyz(ties)
    print(pc)
    while len(pc[flt]) - BACKBONE_NET > 0:
        # calculate the spherical voronoi
        sv = SphericalVoronoi(pc[flt], radius=6371000, threshold=1e-9)
        #vor = Voronoi(lla)

        #fig = voronoi_plot_2d(vor, show_vertices=False, line_colors='orange',
        #                      line_width = 2, line_alpha = 0.6, point_size = 2)
        #plt.show()

        sv.sort_vertices_of_regions()

        area = np.zeros(len(sv.regions))
        weight = np.zeros(len(sv.regions))
        for i, region in enumerate(sv.regions):
            area[i] = calculate_surface_area_of_a_spherical_Voronoi_polygon(
                sv.vertices[region], 6371)
            weight[i] = 0.3 * area[i]  # also needs the stations weight (to do)

        # rank stations by weight
        minw = np.argsort(weight)
        #for m in minw:
        #    print stns[m][0], area[m]

        # remove the first one on the list
        flt[np.where(flt)[0][minw[0]]] = False

        print('iterating %i' % len(pc[flt]))

    plot_v(pc[flt], sv)
    return flt
Beispiel #17
0
def sphere_areas(v):
    """ Calculates areas of Voronoi regions corresponding to given points.

    Args:
        v : numpy array, each column corresponds to a point on the sphere
    Returns:
        1d numpy array, areas of the Voronoi regions corresponding to each of the points
    """
    areas = np.zeros(v.shape[1])
    sv = SphericalVoronoi(v.T)
    # sort the vertices for poly_area()
    sv.sort_vertices_of_regions()
    """
    # (optional) for visualization of the voronoi regions:
    from matplotlib import colors
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import proj3d

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    # plot generator points
    ax.scatter(v[0], v[1], v[2], c='b')
    # plot Voronoi vertices
    ax.scatter(sv.vertices[:, 0], sv.vertices[:, 1], sv.vertices[:, 2], c='g')
    # indicate Voronoi regions (as Euclidean polygons)
    for region in sv.regions:
       random_color = colors.rgb2hex(np.random.rand(3))
       polygon = Poly3DCollection([sv.vertices[region]], alpha=1.0)
       polygon.set_color(random_color)
       ax.add_collection3d(polygon)
    plt.show()
    """
    for j, region in enumerate(sv.regions):
        areas[j] = spherical_poly_area(sv.vertices[region])
    return areas

def to_radius(r, v, c):
    x, y, z = v
    x0, y0, z0 = c
    v = x - x0, y - y0, z - z0
    rho, phi, theta = to_spherical(v, "radians")
    x, y, z = from_spherical(r, phi, theta, "radians")
    return x + x0, y + y0, z + z0


out_verts = []
out_edges = []
out_faces = []

for points, center, radius in zip_long_repeat(in_points, in_center, in_radius):
    if isinstance(radius, (list, tuple)):
        radius = radius[0]
    center = center[0]
    #info("Center: %s, radius: %s", center, radius)
    points = np.array([to_radius(radius, v, center) for v in points])

    vor = SphericalVoronoi(points, radius=radius, center=np.array(center))
    vor.sort_vertices_of_regions()

    new_verts = vor.vertices.tolist()
    new_faces = vor.regions

    out_verts.append(new_verts)
    out_faces.append(new_faces)
Beispiel #19
0
 def test_sort_vertices_of_regions(self):
     sv = SphericalVoronoi(self.points)
     unsorted_regions = sv.regions
     sv.sort_vertices_of_regions()
     assert_array_equal(sorted(sv.regions), sorted(unsorted_regions))
def createGraph(planet, planetGenerator):
    #the sphere is spanned into regions of closer points to the seeds with a spherical Voronoi mapping.
    sv = SphericalVoronoi(planet.meshPoints)
    sv.sort_vertices_of_regions()

    #ensure that the polygon is clockwise oriented and correct it if not.
    #For plotting, all the polygons must have the same orientation.
    for i, region in enumerate(sv.regions):
        if (np.dot(np.cross(sv.points[i], sv.vertices[region[0]]),
                   sv.vertices[region[1]]) > 0):
            sv.regions[i].reverse()

    #the graph of regions centers is created. This is useful for checking travel between regions.
    #At this point it is not yet possible to set the connections between regions.
    centers = Graph(directed=False)
    centers.add_vertex(len(sv.regions))

    #for each cell, register the corners points index delimiting it.
    centers.vertex_properties["corners"] = centers.new_vertex_property(
        "vector<int>")
    for v, corners in zip(centers.vertices(), sv.regions):
        centers.vp.corners[v] = corners

    #for each cell, set its center point.
    centers.vertex_properties["center"] = centers.new_vertex_property(
        "vector<float>")
    for v, center in zip(centers.vertices(), sv.points):
        centers.vp.center[v] = center

    #for each cell, set its area in km^2. This is often used as a weight for the cell.
    centers.vertex_properties["area"] = centers.new_vertex_property("float")
    for v, area in zip(centers.vertices(), sv.calculate_areas()):
        centers.vp.area[v] = area * planet.parameters.radius**2

    #create the graph of corners points. It is the dual of the graph centers.
    #this graph is useful to plot the borders and check touching regions.
    corners = Graph(directed=False)
    corners.add_vertex(len(sv.vertices))

    #for each corner, register its position.
    corners.vertex_properties["position"] = corners.new_vertex_property(
        "vector<float>")
    for v, position in zip(corners.vertices(), sv.vertices):
        corners.vp.position[v] = position

    #set the edges between corners
    cornerLinks = []
    for region in sv.regions:
        cornerLinks += [(min(i, j), max(i, j))
                        for (i, j) in pairwiseRoll(region)]
    #the edges are converted to dictionnary and back to a list to remove the doublons
    corners.add_edge_list(list(dict.fromkeys(cornerLinks)))

    #set the polygons that each corner touches
    corners.vertex_properties["touches"] = corners.new_vertex_property(
        "vector<int>")
    for i, cornerList in enumerate(centers.vp.corners):
        for corner in cornerList:
            corners.vp.touches[corner].append(i)

    #compute length of each border in km
    corners.edge_properties["length"] = corners.new_edge_property("float")
    edges = corners.get_edges()
    positions = np.array(list(corners.vp.position))[edges]
    lengths = np.arccos(np.sum(positions[:, 0] * positions[:, 1],
                               axis=-1)) * planet.parameters.radius
    for i, e in enumerate(corners.edges()):
        corners.ep.length[e] = lengths[i]
    corners.edge_properties["separates"] = corners.new_edge_property(
        "vector<int>")
    for e in corners.edges():
        corners.ep.separates[e] = list(
            set(corners.vp.touches[e.source()]).intersection(
                corners.vp.touches[e.target()]))

    #add links between regions
    centerLinks = []
    for c in corners.vertices():
        l = corners.vp.touches[c]
        centerLinks += [(min(i, j), max(i, j)) for (i, j) in pairwiseRoll(l)]
    centers.add_edge_list(list(dict.fromkeys(centerLinks)))

    #compute distance between regions in km
    centers.edge_properties["length"] = centers.new_edge_property("float")
    edges = centers.get_edges()
    positions = np.array(list(centers.vp.center))[edges]
    lengths = np.arccos(np.sum(positions[:, 0] * positions[:, 1],
                               axis=-1)) * planet.parameters.radius
    for i, e in enumerate(centers.edges()):
        centers.ep.length[e] = lengths[i]

    planet.meshCenters = centers
    planet.meshCorners = corners

    def plotTilesBorders(self, ax, *args, **kwargs):
        edges = self.meshCorners.get_edges()
        segments = np.array(list(self.meshCorners.vp.position))[edges]
        (x, y, z) = np.shape(segments)
        segments = np.reshape(segments, (x * y, z))
        lat, long = Projection().toLatLong(segments)
        lat = np.reshape(lat, (x, y))
        long = np.reshape(long, (x, y))
        lines = [[(slong[0], slat[0]), (slong[1], slat[1])]
                 for slat, slong in zip(lat, long)]
        ax.add_collection(
            mc.LineCollection(lines,
                              *args,
                              transform=ccrs.Geodetic(),
                              **kwargs))

    planet.plotTilesBorders = types.MethodType(plotTilesBorders, planet)

    def plotTilesJunctions(self, ax, *args, **kwargs):
        edges = self.meshCenters.get_edges()
        segments = np.array(list(self.meshCenters.vp.center))[edges]
        (x, y, z) = np.shape(segments)
        segments = np.reshape(segments, (x * y, z))
        lat, long = Projection().toLatLong(segments)
        lat = np.reshape(lat, (x, y))
        long = np.reshape(long, (x, y))
        lines = [[(slong[0], slat[0]), (slong[1], slat[1])]
                 for slat, slong in zip(lat, long)]
        ax.add_collection(
            mc.LineCollection(lines,
                              *args,
                              transform=ccrs.Geodetic(),
                              **kwargs))

    planet.plotTilesJunctions = types.MethodType(plotTilesJunctions, planet)
def main(use_random_set_of_input_points, number_of_random_points, input_samples, input_samples_point_shapefile_output_path, voronoi_polygons_shapefile_output_path, geogr_sr_text):
	
	voronoi_polygon_areas = []
	
	""" We use +- 179.999999 rather than +- 180 deg lon to indicate a date line since -180 deg lon is sometimes automatically 
	converted to +180 deg lon by GDAL/OGR. """
	
	if use_random_set_of_input_points == True:
	
		""" Generate random Points """ 
		
		randomness_generate_random_points(number_of_random_points)
		
		input_samples = random_points
	
	if len(input_samples) < 20:
		print "Need minimum of 20 points for the construction of Voronoi polygons."
		exit()
	
	input_craters_scipy = numpy.array([])
	
	voronoi_out_polygons_geogr_sr = osr.SpatialReference()
	voronoi_out_polygons_geogr_sr.ImportFromWkt(geogr_sr_text)
	
	""" Generate Shapefiles """
	
	# Craters
	
	driver = ogr.GetDriverByName('Esri Shapefile')
	points_data_source = driver.CreateDataSource(input_samples_point_shapefile_output_path)
	points_layer = points_data_source.CreateLayer('Voronoi_Points', voronoi_out_polygons_geogr_sr, geom_type = ogr.wkbPoint)
	
	# Voronoi Polygons
	
	driver = ogr.GetDriverByName('Esri Shapefile')
	voronoi_polygon_data_source = driver.CreateDataSource(voronoi_polygons_shapefile_output_path)
	voronoi_polygon_layer = voronoi_polygon_data_source.CreateLayer('Voronoi_Polygons', voronoi_out_polygons_geogr_sr, geom_type = ogr.wkbPolygon)
	
	area_field_defn = ogr.FieldDefn("Area", ogr.OFTReal)
	voronoi_polygon_layer.CreateField(area_field_defn)
	
	""" Project geographic coordinates to coordinates in 3D space [-1,1] """
	
	point = ogr.Geometry(ogr.wkbPoint)
	point.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
	
	for input_crater in input_samples:
		input_crater_X = input_crater[0]
		input_crater_Y = input_crater[1]	
	
		point.AddPoint(input_crater_X, input_crater_Y)
	
		input_crater_X = math.pi*input_crater_X/180 # Convert to radians
		input_crater_Y = math.pi*input_crater_Y/180
		
		input_crater_Y -= 1.570795765134 # subtract 90 degrees (in radians)
		
		input_crater_X_3D = math.sin(input_crater_Y) * math.cos(input_crater_X)
		input_crater_Z_3D = math.cos(input_crater_Y)
		input_crater_Y_3D = math.sin(input_crater_Y) * math.sin(input_crater_X)
		
		input_craters_scipy = numpy.append(input_craters_scipy, [[input_crater_X_3D, input_crater_Y_3D, input_crater_Z_3D]])
	
		points_featureDefn = points_layer.GetLayerDefn()
		points_feature = ogr.Feature(points_featureDefn)
		points_feature.SetGeometry(point)
		points_layer.CreateFeature(points_feature)
	
	input_craters_scipy.resize((len(input_samples), 3)) # reshape numpy array
	
	""" Calculate Voronoi diagrams on a sphere in 3D space. This only generates vertices on the sphere. Polygon edges cut the sphere's interior. """
		
	sphere_center_coordinates = numpy.array([0, 0, 0])
	sphere_radius = 1
	
	spherical_voronoi = SphericalVoronoi(input_craters_scipy, sphere_radius, sphere_center_coordinates)
	
	spherical_voronoi.sort_vertices_of_regions()
	
	""" Main part of geodesic Voronoi polygon generation: Calculate spherical coordinates of each Voronoi Polygon and save geometries. """
	
	voronoi_count = 0
	
	for spherical_voronoi_region_3D in spherical_voronoi.regions:
		
		voronoi_vertex_count = 1
		voronoi_polygon_area = 0
		
		voronoi_out_polygons = ogr.Geometry(ogr.wkbPolygon)
		voronoi_out_polygons.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
		
		""" Calculate geographic coordinates of polygon vertices """
		
		lons = []
		lats = []
		
		for spherical_voronoi_vertex_3D in spherical_voronoi.vertices[spherical_voronoi_region_3D]:
			spherical_voronoi_vertex_3D_X = spherical_voronoi_vertex_3D[0]
			spherical_voronoi_vertex_3D_Y = spherical_voronoi_vertex_3D[1] 
			spherical_voronoi_vertex_3D_Z = spherical_voronoi_vertex_3D[2]
			
			spherical_voronoi_vertex_lon = math.degrees(math.atan(spherical_voronoi_vertex_3D_Y/spherical_voronoi_vertex_3D_X))
			
			""" Account for atan ambiguity. Otherwise, polygon vertices would all be on the nearside. """
			
			if spherical_voronoi_vertex_3D_X > 0:
				spherical_voronoi_vertex_lon -= 180
				if spherical_voronoi_vertex_lon < -180:
					spherical_voronoi_vertex_lon += 360
					
			spherical_voronoi_vertex_lat = math.degrees(math.asin(spherical_voronoi_vertex_3D_Z))
			
			""" Add vertex to lons[] and lats[] """
	
			lons.append(spherical_voronoi_vertex_lon)
			lats.append(spherical_voronoi_vertex_lat)
			
			if voronoi_vertex_count == 1:
				spherical_voronoi_end_vertex_lon = spherical_voronoi_vertex_lon
				spherical_voronoi_end_vertex_lat = spherical_voronoi_vertex_lat
			
			voronoi_vertex_count += 1
		
		""" Close ring """
		
		lons.append(spherical_voronoi_end_vertex_lon)
		lats.append(spherical_voronoi_end_vertex_lat)
		
		""" define reprojections from input craters (center of voronoi polygon) """
		
		center_voronoi_polygon_X = input_samples[voronoi_count][0]
		center_voronoi_polygon_Y = input_samples[voronoi_count][1]
		
		voronoi_LAEA_text = 'PROJCS["PROJECTED_LAMBERT_AEA",'+str(voronoi_out_polygons_geogr_sr)+',PROJECTION["Lambert_Azimuthal_Equal_Area"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["central_meridian",'+str(center_voronoi_polygon_X)+'],PARAMETER["latitude_of_origin",'+str(center_voronoi_polygon_Y)+'],UNIT["Meter",1.0]]'
		voronoi_LAEA_sr = osr.SpatialReference()
		voronoi_LAEA_sr.ImportFromWkt(voronoi_LAEA_text)
	
		voronoi_geogr_text = re.sub('(PRIMEM)(.*)(,)', r'\1["Reference_Meridian",' + str(center_voronoi_polygon_X) + '],', str(voronoi_out_polygons_geogr_sr))
		voronoi_geogr_sr = osr.SpatialReference()
		voronoi_geogr_sr.ImportFromWkt(voronoi_geogr_text)
		
		""" define reprojections """
		
		geogr_to_proj_voronoi = osr.CoordinateTransformation(voronoi_out_polygons_geogr_sr, voronoi_LAEA_sr)
		proj_voronoi_to_geogr = osr.CoordinateTransformation(voronoi_LAEA_sr, voronoi_out_polygons_geogr_sr)
		
		proj_voronoi_to_geogr_voronoi = osr.CoordinateTransformation(voronoi_LAEA_sr, voronoi_geogr_sr)
		geogr_voronoi_to_proj_voronoi = osr.CoordinateTransformation(voronoi_geogr_sr, voronoi_LAEA_sr)
	
		""" define polygons that eventually become a voronoi polygon """
		
		voronoi_ring = ogr.Geometry(ogr.wkbLinearRing)
		voronoi_ring.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
		
		voronoi_ring_dateline_intersection = ogr.Geometry(ogr.wkbLinearRing)
		voronoi_ring_dateline_intersection.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
		
		major_axis = voronoi_out_polygons_geogr_sr.GetSemiMajor()
		minor_axis = voronoi_out_polygons_geogr_sr.GetSemiMinor()
		flattening = (major_axis-minor_axis) / major_axis
		
		""" Use vertices of voronoi polygons to calculate geodesic polygon edges. """
		
		voronoi_vertex_lat_lon_count = 0
		voronoi_date_line_intersection_count = 0
		
		for voronoi_vertex_lon in lons:
			voronoi_vertex_lat = lats[voronoi_vertex_lat_lon_count]
			
			if voronoi_vertex_lat_lon_count+1 < len(lons):
				voronoi_next_vertex_lat = lats[voronoi_vertex_lat_lon_count+1]
				voronoi_next_vertex_lon = lons[voronoi_vertex_lat_lon_count+1]
				
			if voronoi_vertex_lat_lon_count+1 >= len(lons):
				
				if voronoi_date_line_intersection_count % 2 == 0: 	
					voronoi_ring.AddPoint(lons[0], lats[0])
					
				if voronoi_date_line_intersection_count % 2 == 1: 	
					voronoi_ring_dateline_intersection.AddPoint(lons[0], lats[0])
				continue
			
			if voronoi_date_line_intersection_count % 2 == 0: 
				voronoi_ring.AddPoint(voronoi_vertex_lon, voronoi_vertex_lat)
			
			if voronoi_date_line_intersection_count % 2 == 1: 	
				voronoi_ring_dateline_intersection.AddPoint(voronoi_vertex_lon, voronoi_vertex_lat)
			
			""" Get distance and azimuth between voronoi vertices. """
			
			inverse_vincenty(flattening, major_axis, voronoi_vertex_lat, voronoi_vertex_lon, voronoi_next_vertex_lat, voronoi_next_vertex_lon)
			geodesic_distance_between_voronoi_vertices = geodesic_distance_crater_area
			azimuth_between_voronoi_vertices = direction12
			
			distance_geodesic_polygon_vertices = 0
			geodesic_voronoi_vertices_count = 0
			
			""" Mark scipy voronoi vertex as 'previous vertex' in geodesic edge calculation. This is done to consider Date Line intersections 
			that occur between the voronoi vertex and the first geodesic vertex (less than 15 km away).   """
			
			if geodesic_voronoi_vertices_count == 0:
				previous_voronoi_geodesic_vertex_X = voronoi_vertex_lon
				previous_voronoi_geodesic_vertex_Y = voronoi_vertex_lat
			
			""" Divide distance between vertices into 15 km segments and get coordinates of vertices. Vertices from geodesic distances are added to voronoi_ring. """
			
			geodesic_distance_voronoi_vertices = 15000 
			
			""" When vertices of a polygon are closer than the segment length of the geodesic vertices, the distance between geodesic vertices is reduced to 
			one fifth of the distance between the vertices (to get additional vertex in between). When start and end 
			vertex of a polygon are close to the date line on either hemisphere, this would cause the program to believe that there is a polar intersection 
			(because there is only one date line intersection present due to the missing additional vertices over the second date line intersection) 
			resulting in wrong voronoi polygons. """
			
			if geodesic_distance_crater_area < geodesic_distance_voronoi_vertices:
				geodesic_distance_voronoi_vertices = geodesic_distance_crater_area/5
			
			""" When the current or the next vertex is very close to the date line, make sure that the distance between the geodesic vertices in between 
			is lower than that. If not considered, a date line intersection would be recognized as a polar intersection because the second date line overlap 
			would not occur as planned. If either vertex is <-170 deg lon or >170 deg lon (10 deg lon can be very short close to the poles), check distance to date line and if either distance is lower 
			than the geodesic distance to calculate the vertices in between, modify the geodesic distance. """
			
			voronoi_date_line_correction_lon_1 = 170
			voronoi_date_line_correction_lon_2 = -170
			
			""" Close to the poles, a vertex is considered very close to the date line when it is closer than +- 150 deg lon. """
			
			if voronoi_vertex_lat > 89 or voronoi_vertex_lat < -89:
				voronoi_date_line_correction_lon_1 = 150
				voronoi_date_line_correction_lon_2 = -150			
				
			if voronoi_vertex_lon < voronoi_date_line_correction_lon_2 or voronoi_next_vertex_lon < voronoi_date_line_correction_lon_2 or voronoi_vertex_lon > voronoi_date_line_correction_lon_1 or voronoi_next_vertex_lon > voronoi_date_line_correction_lon_1:
				if voronoi_vertex_lon > voronoi_date_line_correction_lon_1 or voronoi_next_vertex_lon > voronoi_date_line_correction_lon_1:
					shapely_dateline = LineString([(180, 90),(180, 0),(180, -90)])
				if voronoi_vertex_lon < voronoi_date_line_correction_lon_2 or voronoi_next_vertex_lon < voronoi_date_line_correction_lon_2:
					shapely_dateline = LineString([(-180, 90),(-180, 0),(-180, -90)])
				
				""" Find closest point on Date Line and get geodesic distance. """
				
				shapely_voronoi_vertex = Point(voronoi_vertex_lon, voronoi_vertex_lat)
				shapely_next_voronoi_vertex = Point(voronoi_next_vertex_lon, voronoi_next_vertex_lat)
				
				voronoi_vertex_closest_point_on_dateline = shapely_dateline.interpolate(shapely_dateline.project(shapely_voronoi_vertex))
				voronoi_next_vertex_closest_point_on_dateline = shapely_dateline.interpolate(shapely_dateline.project(shapely_next_voronoi_vertex))
				 
				voronoi_vertex_closest_point_on_dateline_ogr = ogr.CreateGeometryFromWkt(voronoi_vertex_closest_point_on_dateline.wkt)
				voronoi_next_vertex_closest_point_on_dateline_ogr = ogr.CreateGeometryFromWkt(voronoi_next_vertex_closest_point_on_dateline.wkt)
				
				voronoi_vertex_closest_point_on_dateline_ogr_X = voronoi_vertex_closest_point_on_dateline_ogr.GetX()
				voronoi_vertex_closest_point_on_dateline_ogr_Y = voronoi_vertex_closest_point_on_dateline_ogr.GetY()
				
				voronoi_next_vertex_closest_point_on_dateline_ogr_X = voronoi_next_vertex_closest_point_on_dateline_ogr.GetX()
				voronoi_next_vertex_closest_point_on_dateline_ogr_Y = voronoi_next_vertex_closest_point_on_dateline_ogr.GetY()
				
				inverse_vincenty(flattening, major_axis, voronoi_vertex_lat, voronoi_vertex_lon, voronoi_vertex_closest_point_on_dateline_ogr_Y, voronoi_vertex_closest_point_on_dateline_ogr_X)		
				distance_voronoi_vertex_closest_point_on_dateline = geodesic_distance_crater_area
				
				inverse_vincenty(flattening, major_axis, voronoi_next_vertex_lat, voronoi_next_vertex_lon, voronoi_next_vertex_closest_point_on_dateline_ogr_Y, voronoi_next_vertex_closest_point_on_dateline_ogr_X)			
				distance_next_voronoi_vertex_closest_point_on_dateline = geodesic_distance_crater_area
				
				""" Check whether the current or the next vertex is closest to the date line. """
				
				minimum_distance_current_and_next_voronoi_vertex_to_dateline = min(distance_voronoi_vertex_closest_point_on_dateline, distance_next_voronoi_vertex_closest_point_on_dateline)
				
				""" Use closest distance to the date line to modify the distance between the geodesic vertices for such polygon sections. """
				
				if minimum_distance_current_and_next_voronoi_vertex_to_dateline < 2 * geodesic_distance_voronoi_vertices:
					geodesic_distance_voronoi_vertices = minimum_distance_current_and_next_voronoi_vertex_to_dateline/5
				
			while geodesic_distance_between_voronoi_vertices > geodesic_distance_voronoi_vertices:
				distance_geodesic_polygon_vertices += geodesic_distance_voronoi_vertices
				geodesic_distance_between_voronoi_vertices -= geodesic_distance_voronoi_vertices
				
				direct_vincenty(flattening, major_axis, [[voronoi_vertex_lon, voronoi_vertex_lat, azimuth_between_voronoi_vertices, 0, 0]], distance_geodesic_polygon_vertices, 1)
				
				voronoi_geodesic_vertex_X = buffer_vertices_list[0][0]
				voronoi_geodesic_vertex_Y = buffer_vertices_list[0][1]
				
				""" Consideration of Date Line intersections. If the voronoi polygon crosses the Date Line, the voronoi polygon is merged from 
				individual polygons voronoi_ring and voronoi_ring_dateline_intersection to avoid Date Line ambiguity. """
				
				""" Polygons that intersect the date line cross the date line twice, polygons that intersect the poles intersect the date line once """
					
				""" detect intersection with date line """
				
				voronoi_dateline_intersection = False
				
				if previous_voronoi_geodesic_vertex_X <= 179.999999 and voronoi_geodesic_vertex_X > 179.999999 or previous_voronoi_geodesic_vertex_X > 179.999999 and voronoi_geodesic_vertex_X <= 179.999999:# or previous_voronoi_start_vertex_X <= 179.999999 and voronoi_geodesic_vertex_X > 179.999999 or previous_voronoi_start_vertex_X > 179.999999 and voronoi_geodesic_vertex_X <= 179.999999:
					voronoi_dateline_intersection = True
					voronoi_dateline_hemisphere = "East"
					
					dateline_voronoi = ogr.Geometry(ogr.wkbLineString)
					dateline_voronoi.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
					dateline_voronoi.AddPoint(179.999999, 90)
					dateline_voronoi.AddPoint(179.999999, -90)		
				
				if previous_voronoi_geodesic_vertex_X >= -179.999999 and voronoi_geodesic_vertex_X < -179.999999 or previous_voronoi_geodesic_vertex_X < -179.999999 and voronoi_geodesic_vertex_X >= -179.999999:# or previous_voronoi_start_vertex_X >= -179.999999 and voronoi_geodesic_vertex_X < -179.999999 or previous_voronoi_start_vertex_X < -179.999999 and voronoi_geodesic_vertex_X >= -179.999999:
					voronoi_dateline_intersection = True
					voronoi_dateline_hemisphere = "West"
					
					dateline_voronoi = ogr.Geometry(ogr.wkbLineString)
					dateline_voronoi.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
					dateline_voronoi.AddPoint(-179.999999, 90)
					dateline_voronoi.AddPoint(-179.999999, -90)		
				
				if voronoi_dateline_intersection ==  True:
					voronoi_date_line_intersection_count += 1
		
					previous_current_voronoi_vertex_line = ogr.Geometry(ogr.wkbLineString)
					previous_current_voronoi_vertex_line.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
					previous_current_voronoi_vertex_line.AddPoint(previous_voronoi_geodesic_vertex_X, previous_voronoi_geodesic_vertex_Y)
					previous_current_voronoi_vertex_line.AddPoint(voronoi_geodesic_vertex_X, voronoi_geodesic_vertex_Y)						
					
					voronoi_dateline_intersection_point = previous_current_voronoi_vertex_line.Intersection(dateline_voronoi)
					
					voronoi_dateline_intersection_point_X = voronoi_dateline_intersection_point.GetX()
					voronoi_dateline_intersection_point_Y = voronoi_dateline_intersection_point.GetY()
			
					""" add date line intersection point to voronoi_ring """
					
					if voronoi_date_line_intersection_count % 2 == 1:
						voronoi_ring.AddPoint(voronoi_dateline_intersection_point_X, voronoi_dateline_intersection_point_Y)
					
					""" When crossing to the other hemisphere for the first time, the new polygon longitude must always be -179.999999 if it crosses 
					from west to east and +179.999999 when crossing from east to west. This is the first intersection point with the date line. """
					
					if voronoi_dateline_hemisphere == "East":
						voronoi_dateline_intersection_point_X = -179.999999	
						
					if voronoi_dateline_hemisphere == "West":
						voronoi_dateline_intersection_point_X = +179.999999	
	
					if voronoi_date_line_intersection_count % 2 == 0:
						voronoi_ring.AddPoint(voronoi_dateline_intersection_point_X, voronoi_dateline_intersection_point_Y)
					
					""" When crossing back to the other hemisphere, the new polygon longitude must always be +179.999999 if it crosses from west to east and -179.999999 
					when crossing from east to west. This is the second intersection point with the date line. """
					
					if voronoi_date_line_intersection_count % 2 == 0:
						if voronoi_dateline_hemisphere == "East":
							voronoi_dateline_intersection_point_X = 179.999999	
							
						if voronoi_dateline_hemisphere == "West":
							voronoi_dateline_intersection_point_X = -179.999999
					
					""" add intersection point to second voronoi ring, voronoi_ring_dateline_intersection """
					
					voronoi_ring_dateline_intersection.AddPoint(voronoi_dateline_intersection_point_X, voronoi_dateline_intersection_point_Y)
					
					if voronoi_date_line_intersection_count % 2 == 1:
						old_voronoi_dateline_intersection_point_X = voronoi_dateline_intersection_point_X
						old_voronoi_dateline_intersection_point_Y = voronoi_dateline_intersection_point_Y
					
					""" when entering back to the other hemisphere, add voronoi_ring_dateline_intersection to the voronoi polygon and create a new 
					voronoi_ring_dateline_intersection polygon in case there is another date line intersection """
					
					if voronoi_date_line_intersection_count % 2 == 0: 
						
						""" add first date line intersection point to close ring """
						
						""" When crossing back to the other hemisphere, the new polygon longitude must always be +179.999999 if it crosses from west to east and -179.999999 
						when crossing from east to west. This is the closing point for the polygon (the first intersection point). """
							
						if voronoi_dateline_hemisphere == "East":
							old_voronoi_dateline_intersection_point_X = 179.999999	
							
						if voronoi_dateline_hemisphere == "West":
							old_voronoi_dateline_intersection_point_X = -179.999999
						
						
						voronoi_ring_dateline_intersection.AddPoint(old_voronoi_dateline_intersection_point_X, old_voronoi_dateline_intersection_point_Y)
						
						""" add voronoi_ring_dateline_intersection to voronoi polygon """
						
						voronoi_out_polygons.AddGeometry(voronoi_ring_dateline_intersection)
						
						""" get area of voronoi_ring_dateline_intersection. area of voronoi polygon is summed."""
						
						voronoi_ring_dateline_intersection.Transform(geogr_to_proj_voronoi)
						voronoi_ring_dateline_intersection_area = voronoi_ring_dateline_intersection.GetArea()
						voronoi_ring_dateline_intersection.Transform(proj_voronoi_to_geogr)
						
						voronoi_polygon_area += voronoi_ring_dateline_intersection_area
						
						""" Create a new empty voronoi_ring_dateline_intersection in case there is another date line intersection coming up. """
						
						voronoi_ring_dateline_intersection = ogr.Geometry(ogr.wkbLinearRing)
						voronoi_ring_dateline_intersection.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
				
				""" remember current vertex """
				
				previous_voronoi_geodesic_vertex_X = voronoi_geodesic_vertex_X
				previous_voronoi_geodesic_vertex_Y = voronoi_geodesic_vertex_Y
				
				""" Correct coordinates so that lon is between -179.999999 and +179.999999 deg, to avoid 'jumps' in polygons. Values outside this range are still used to 
				determine the presence of date line intersections and the calculation of geodesic coordinates (Vincenty) """ 
				
				if voronoi_geodesic_vertex_X < -179.999999:
					voronoi_geodesic_vertex_X += 360
				if voronoi_geodesic_vertex_X > 179.999999:
					voronoi_geodesic_vertex_X -= 360
					
				""" Vertices from geodesic distance calculations are added either to voronoi_ring (no date line intersection) or 
				voronoi_ring_dateline_intersection (date line intersection). """
				
				if voronoi_date_line_intersection_count % 2 == 0: 
					voronoi_ring.AddPoint(voronoi_geodesic_vertex_X, voronoi_geodesic_vertex_Y)
				
				if voronoi_date_line_intersection_count % 2 == 1: 	
					voronoi_ring_dateline_intersection.AddPoint(voronoi_geodesic_vertex_X, voronoi_geodesic_vertex_Y)
				
				geodesic_voronoi_vertices_count += 1
			
			voronoi_vertex_lat_lon_count += 1
		
		""" Here, the processing of a voronoi polygon is finished. If during processing there was only one intersection with the dateline 
		and no crossing back over the date line, the current voronoi polygon intersects the poles. Here, we draw a new polygon from the voronoi_ring 
		and voronoi_ring_dateline_intersection vertices. We check whether there is a north pole or south pole intersection and add the respective pole 
		and the longitudinally-ordered vertices to the polar intersection voronoi polygon. """
		
		if voronoi_date_line_intersection_count % 2 == 1:
			
			""" get all vertices in voronoi_ring and voronoi_ring_dateline_intersection and sort them according to their longitudes """
			
			voronoi_polar_intersection_vertices = []
			
			for voronoi_polar_vertex in range(0, voronoi_ring_dateline_intersection.GetPointCount()):
				voronoi_polar_vertex_coordinates = voronoi_ring_dateline_intersection.GetPoint(voronoi_polar_vertex)
				voronoi_polar_vertex_lon = voronoi_polar_vertex_coordinates[0]
				voronoi_polar_vertex_lat = voronoi_polar_vertex_coordinates[1]	
				
				voronoi_polar_intersection_vertices.append([voronoi_polar_vertex_lon, voronoi_polar_vertex_lat])
			
			for voronoi_polar_vertex in range(0, voronoi_ring.GetPointCount()):
				voronoi_polar_vertex_coordinates = voronoi_ring.GetPoint(voronoi_polar_vertex)
				voronoi_polar_vertex_lon = voronoi_polar_vertex_coordinates[0]
				voronoi_polar_vertex_lat = voronoi_polar_vertex_coordinates[1]	
				
				voronoi_polar_intersection_vertices.append([voronoi_polar_vertex_lon, voronoi_polar_vertex_lat])
				
			voronoi_polar_intersection_vertices = sorted(voronoi_polar_intersection_vertices, key=lambda coordinates: coordinates[0]) 
			
			""" find pole that is closest to the impact crater - we assume that this indicates whether this is an intersection with the north pole or the south pole """
			
			inverse_vincenty(flattening, major_axis, center_voronoi_polygon_Y, center_voronoi_polygon_X, 89.99999, 0)			
			distance_crater_north_pole = geodesic_distance_crater_area
	
			inverse_vincenty(flattening, major_axis, center_voronoi_polygon_Y, center_voronoi_polygon_X, -89.99999, 0)			
			distance_crater_south_pole = geodesic_distance_crater_area
			
			if distance_crater_north_pole <= distance_crater_south_pole:
				voronoi_polar_vertex_Y = 89.99999
				
			if distance_crater_north_pole > distance_crater_south_pole:
				voronoi_polar_vertex_Y = -89.99999
			
			""" Draw a new polygon (voronoi_ring) for polar intersections. The poles and date lines are not exactly at +- 179.999999 deg lon or +-90 deg lat. 
			Date lines are sometimes automatically converted from -179.999999 to +179.999999 degrees in OGR which is not very helpful in this case. 
			Polar intersections may result in gaps if the latitude is set to +- 90 deg. """
			
			voronoi_ring = ogr.Geometry(ogr.wkbLinearRing)
			voronoi_ring.AssignSpatialReference(voronoi_out_polygons_geogr_sr)
			
			voronoi_ring.AddPoint(-179.99999, voronoi_polar_vertex_Y) # closest pole
			
			for voronoi_polar_intersection_vertex in voronoi_polar_intersection_vertices:
				voronoi_polar_intersection_vertex_X = voronoi_polar_intersection_vertex[0]
				voronoi_polar_intersection_vertex_Y = voronoi_polar_intersection_vertex[1]
				
				if voronoi_polar_intersection_vertex_X == -179.999999:
					voronoi_polar_intersection_vertex_X = -179.99999
					
				if voronoi_polar_intersection_vertex_X == 179.999999:
					voronoi_polar_intersection_vertex_X = 179.99999
					
				voronoi_ring.AddPoint(voronoi_polar_intersection_vertex_X, voronoi_polar_intersection_vertex_Y)
				
			voronoi_ring.AddPoint(179.99999, voronoi_polar_vertex_Y) # closest pole	
	
		voronoi_count += 1	
		
		print voronoi_count
		print "---"
		
		""" Get area of voronoi_ring. The total area is eventually summed from voronoi_ring and voronoi_ring_dateline_intersection due to 
		inaccurate area measurements when one polygon intersects the date line intersections. """
		
		voronoi_ring.Transform(geogr_to_proj_voronoi)
		voronoi_ring_area = voronoi_ring.GetArea()
		voronoi_ring.Transform(proj_voronoi_to_geogr)
		
		voronoi_polygon_area += voronoi_ring_area 
		voronoi_polygon_areas.append(voronoi_polygon_area)
		
		""" Add geometry to shapefile """
		
		voronoi_out_polygons.AddGeometry(voronoi_ring)
		
		voronoi_polygons_featureDefn = voronoi_polygon_layer.GetLayerDefn()
		voronoi_polygon_feature = ogr.Feature(voronoi_polygons_featureDefn)
		voronoi_polygon_feature.SetGeometry(voronoi_out_polygons)
		voronoi_polygon_feature.SetField("Area", voronoi_polygon_area)
		voronoi_polygon_layer.CreateFeature(voronoi_polygon_feature)
	
	print "Done."
 def test_sort_vertices_of_regions(self):
     sv = SphericalVoronoi(self.points)
     unsorted_regions = sv.regions
     sv.sort_vertices_of_regions()
     assert_array_equal(sorted(sv.regions), sorted(unsorted_regions))
Beispiel #23
0
def getVoronoiCollection(data, lat_name, lon_name, bmap = None, v_name = None, full_sphere = False, 
                         max_v=.3, min_v=-0.3, cmap = cm.get_cmap('jet'), test_point = None,
                         proj1=None, proj2=None, **kwargs):
    '''
    Perform a Spherical Voronoi Tessellation on the input data.
    In the case where the data is restricted to one part of the globe, a polygon will not be returned
    for all objects, as matplotlib polygons won't be able to stretch over half the globe. 
    @param data: Input pandas data frame
    @param lat_name: Name of latitude column
    @param lon_name: Name of longitude column
    @param bmap: Basemap instance used to convert from lat, lon coordinates to projection coordinates
    @param v_name: Name of value column. Use this to color each cell according to a value.
    @param full_sphere: Set to true if the data spans the entire globe. 
                        If false, a fictional point is created during tessellation and 
                        removed later to work around issues when polygons are suppose to 
                        span the over half the globe.
    @param max_v: Specify a maximum value to use when assigning values to the tessellation
    @param min_v: Specify a minimum value to use when assigning values to the tessellation
    @param cmap: Matplotlib color map to use
    @param test_point: Tuple containing the latitude and longitude of the ficitonal point to used to remove polygons that
                       wrap around the earth. If none, a point is automatically chosen
    @param proj1: PyProj projection of input coordinates
    @param proj2: PyProj projection of sphere
    @return Matplotlib patch collection of tessellation, scipy.spatial.SphericalVoronoi object, integer index of objects in patch collection.
    '''

    data = data.copy()

    if full_sphere == False:
        if test_point == None:
            test_lat = -1*np.mean(data[lat_name])
            test_lon = np.mean(data[lon_name]) + 180

        else:
            test_lat = test_point[0]
            test_lon = test_point[1]
    
        full_data = data
        full_data = pd.concat([full_data, pd.DataFrame({lat_name: test_lat, lon_name: test_lon}, 
                                                        index=[full_data.index[0]])])
        
        full_data.set_index(np.arange(len(full_data)), inplace=True)

        
    else:
        full_data = data
        
    # print(full_data.tail())

    if proj1 != None and proj2 != None:
        results = pyproj.transform(proj1, proj2, full_data[lon_name].as_matrix(), full_data[lat_name].as_matrix())
        full_data[lon_name] = results[0]
        full_data[lat_name] = results[1]

    xyz = pd.DataFrame(sphericalToXYZ(full_data[lat_name], full_data[lon_name]),columns=['x','y','z'],index=full_data.index)
    
    if v_name != None:
        full_data = pd.concat([full_data.loc[:,[lat_name,lon_name, v_name]],xyz],axis=1)
    else:
        full_data = pd.concat([full_data.loc[:,[lat_name,lon_name, v_name]],xyz],axis=1)
        
    unique_index = np.unique(full_data.loc[:,lat_name] + 1j*full_data.loc[:,lon_name],return_index=True)[1]
    
    full_data = full_data.iloc[np.sort(unique_index)]
    
    voronoi = SphericalVoronoi(full_data.loc[:,['x','y','z']].as_matrix(), **kwargs)
    
    voronoi.sort_vertices_of_regions()
    
    #latlon_verts = xyzToSpherical(voronoi.vertices[:,0],voronoi.vertices[:,1], voronoi.vertices[:,2])
    
    #if proj1 != None and proj2 != None:
    #    results = pyproj.transform(proj2, proj1, latlon_verts[:,1], latlon_verts[:,0])
    #    latlon_verts[:, 1] = results[0]
    #    latlon_verts[:, 0] = results[1]
        
    #matches = list(map(lambda x: find_match(x, voronoi.regions), range(len(voronoi.regions))))
    
    #patch_list = []
    #patch_index = []

    #for i, (region,match,(station,row)) in enumerate(zip(voronoi.regions,matches, full_data.iterrows())):

     #   if full_sphere or (len(matches)-1) not in match:
            # Keep an index of regions in patchcollection
     #       patch_index.append(i)

     #       if bmap != None:
     #           xy = np.array(bmap(latlon_verts[region,1],latlon_verts[region,0])).T
     #       else:
     #           xy = np.array([latlon_verts[region,1],latlon_verts[region,0]]).T
                
            
     #       if v_name != None:
     #           value = row[v_name]
     #           scaled_value = (value - min_v) / (max_v - min_v)
     #           if scaled_value > 1:
     #               scaled_value = 1.0
     #           elif scaled_value < 0:
     #               scaled_value = 0.0

     #           poly = Polygon(xy, fill=True,facecolor = cmap(scaled_value),edgecolor=cmap(scaled_value))
                
     #       else:
     #           poly = Polygon(xy, fill=False)
     #           
     #       patch_list.append(poly)

    return voronoi
Beispiel #24
0
x0, y0, z0 = 0, 0, 0
SphCart(1, np.random.rand(200)*np.pi*2, np.random.rand(200)*np.pi)
points = np.random.normal(size = (3,200))
points /= np.linalg.norm(points, axis = 0)
points = points.T


radius = 1

center = np.array([x0, y0, z0])

sv = SphericalVoronoi(points, radius, center)

# sort vertices (optional, helpful for plotting)

sv.sort_vertices_of_regions()

fig = plt.figure()

ax = fig.add_subplot(111, projection='3d')

# plot the unit sphere for reference (optional)

u = np.linspace(0, 2 * np.pi, 100)

v = np.linspace(0, np.pi, 100)

x = np.outer(np.cos(u), np.sin(v))

y = np.outer(np.sin(u), np.sin(v))
Beispiel #25
0
class Model:
    @staticmethod
    def arrangedPointsOnSphere(n):
        indices = np.arange(n).astype(np.float32) + 0.5
        thetas = np.pi * (1 + 5**0.5) * indices
        phis = np.arccos(1 - 2 * indices / indices.shape[0])
        widths = np.sin(phis)
        heights = np.cos(phis)
        return np.array(
            [widths * np.cos(thetas), heights, widths * np.sin(thetas)]).T

    @staticmethod
    def randomPointsOnSphere(n):
        thetas = 2 * np.pi * np.random.sample(n).astype(np.float32)
        heights = 2 * np.random.sample(n).astype(np.float32) - 1
        widths = (1 - heights**2)**0.5
        return np.array(
            [widths * np.cos(thetas), heights, widths * np.sin(thetas)]).T

    def __init__(self, count):
        np.random.seed()
        self.vertices = self.randomPointsOnSphere(count)
        self.translations = np.zeros(self.vertices.shape, dtype=np.float32)
        self.invalidate()

    def invalidate(self):
        self.sv = None

    def needsUpdate(self):
        return self.sv is None

    def count(self):
        return self.vertices.shape[0]

    def temperature(self):
        return np.square(self.translations).sum()

    def addVerticesAt(self, positions):
        newVertices = positions / np.linalg.norm(positions, axis=1)[:,
                                                                    np.newaxis]
        newTranslations = np.zeros_like(newVertices)
        self.vertices = np.append(self.vertices, newVertices, axis=0)
        self.translations = np.append(self.translations,
                                      newTranslations,
                                      axis=0)
        self.invalidate()

    def addVertices(self, count):
        newVertices = self.randomPointsOnSphere(count)
        self.addVerticesAt(newVertices)

    def vertexIdAt(self, pos):
        return np.dot(self.vertices, pos).argmax()

    def resetVertex(self, i, pos):
        self.vertices[i] = pos / np.linalg.norm(pos)
        self.translations[i] = 0
        self.invalidate()

    def resetAllVertices(self, random):
        makePoints = self.randomPointsOnSphere if random else self.arrangedPointsOnSphere

        self.vertices = makePoints(self.count())
        self.translations[:] = 0
        self.invalidate()

    def removeVertexIds(self, ids):
        self.vertices = np.delete(self.vertices, ids, axis=0)
        self.translations = np.delete(self.translations, ids, axis=0)
        self.invalidate()

    def removeVertices(self, count):
        count = min(count, self.count() - 4)
        ids = self.vertices.shape[0] - count + np.arange(count)
        self.removeVertexIds(ids)

    def _updateSV(self):
        self.sv = SphericalVoronoi(self.vertices)
        self.sv.sort_vertices_of_regions()

    def _updateVertices(self):
        self.allVertices = np.append(self.vertices,
                                     self.sv.vertices).astype(np.float32)

    def _updateLinks(self):
        links = [set() for _ in self.vertices]
        for simplex in self.sv._simplices:
            a, b, c = simplex[0], simplex[1], simplex[2]
            links[a].update((b, c))
            links[b].update((a, c))
            links[c].update((a, b))

        self.degrees = np.empty(len(links), dtype=np.int32)
        self.links = np.empty(len(links), dtype=np.object_)
        for i, ends in enumerate(links):
            degree = len(ends)
            array = np.empty((degree, 2), np.int32)
            array[:, 0] = i
            array[:, 1] = np.fromiter(ends, np.int32)
            self.links[i] = array
            self.degrees[i] = degree

    def _updateBordersAndTris(self):
        self.tris = np.empty(len(self.sv.regions), dtype=np.object_)
        self.borders = np.empty(len(self.sv.regions), dtype=np.object_)
        for i, region in enumerate(self.sv.regions):
            array = np.array(region) + self.count()
            tris = np.empty((array.size, 3), np.int32)
            borders = np.empty((array.size, 2), np.int32)
            tris[:, 0] = i
            tris[0, 1] = borders[0, 0] = array[-1]
            tris[1:, 1] = borders[1:, 0] = array[:-1]
            tris[:, 2] = borders[:, 1] = array
            self.tris[i] = tris
            self.borders[i] = borders

    def updateGeometry(self):
        self._updateSV()
        self._updateVertices()
        self._updateLinks()
        self._updateBordersAndTris()
def voronoi_plot(points_in, losses, path, cmap):
    from matplotlib import colors
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection
    import matplotlib.pyplot as plt
    from scipy.spatial import SphericalVoronoi
    from mpl_toolkits.mplot3d import proj3d
    # get input points in correct format
    cart = [point['cartesian'] for point in points_in]
    points = np.array(cart)
    center = np.array([0, 0, 0])
    radius = 1
    # calculate spherical Voronoi diagram
    sv = SphericalVoronoi(points, radius, center)
    # sort vertices (optional, helpful for plotting)
    sv.sort_vertices_of_regions()
    # generate plot
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    # plot the unit sphere for reference (optional)
    u = np.linspace(0, 2 * np.pi, 100)
    v = np.linspace(0, np.pi, 100)
    x = np.outer(np.cos(u), np.sin(v))
    y = np.outer(np.sin(u), np.sin(v))
    z = np.outer(np.ones(np.size(u)), np.cos(v))
    ax.plot_surface(x, y, z, color='y', alpha=0.1)
    ax.grid(False)
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_zticks([])
    plt.axis('off')

    # normalize and map losses to colormap
    mi = min(losses)
    ma = max(losses)

    norm = matplotlib.colors.Normalize(vmin=mi, vmax=ma, clip=True)
    mapper = cm.ScalarMappable(norm=norm, cmap=cmap)

    loss_color = [mapper.to_rgba(l) for l in losses]

    # indicate Voronoi regions (as Euclidean polygons)
    for i in range(len(sv.regions)):
        region = sv.regions[i]
        random_color = colors.rgb2hex(loss_color[i])
        polygon = Poly3DCollection([sv.vertices[region]], alpha=1.0)
        polygon.set_color(random_color)
        ax.add_collection3d(polygon)

    fig.savefig(os.path.join(path, "landscape.png"), dpi=fig.dpi)

    # determine neighbours
    neighbours = []
    for i in range(len(sv.regions)):
        vertices = sv.regions[i]
        neighbours_for_i = []
        for j in range(len(sv.regions)):
            neigh = False
            shared = 0
            vert2 = sv.regions[j]
            for vert in vertices:
                if vert in vert2:
                    shared += 1
                    if shared >= 2:
                        neigh = True
                        break
            if neigh and i != j:
                neighbours_for_i.append(j)
        neighbours.append(neighbours_for_i)

    regions, steepest_neighbour = steepest_region(neighbours, losses)
    #plot_boundaries(regions, neighbours, sv, ax)

    temp = []
    for i in range(len(neighbours)):
        point1 = sv.points[i]
        point2 = points[steepest_neighbour[i]]
        temp.append(point2 - point1)

    x1, y1, z1 = zip(*sv.points)
    dx, dy, dz = zip(*temp)

    col = [[0, 0, 0, 0.5] for i in range(len(neighbours))]
    #ax.quiver(x1, y1, z1, dx, dy, dz, length=0.02, normalize=True, colors=col) # uncomment this get directional arrows as well

    num_sets = len(regions)
    colors = cm.rainbow(np.linspace(0, 1, num_sets))

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.plot_surface(x, y, z, color='y', alpha=0.1)
    ax.grid(False)
    ax.set_xticks([])
    ax.set_yticks([])
    ax.set_zticks([])
    plt.axis('off')

    # indicate Voronoi regions (as Euclidean polygons)
    i = 0
    centers = []
    for reg in regions:
        set = regions[reg]['region_set']
        centers.append(reg)
        for index in set:
            region = sv.regions[index]
            polygon = Poly3DCollection([sv.vertices[region]], alpha=1.0)
            polygon.set_color(colors[i])
            ax.add_collection3d(polygon)
        i += 1

    x_p, y_p, z_p = zip(*sv.points)
    x_p = [x_p[i] for i in centers]
    y_p = [y_p[i] for i in centers]
    z_p = [z_p[i] for i in centers]
    ax.scatter(x_p, y_p, z_p, c='k', s=1)
    fig.savefig(os.path.join(path, "regions.png"), dpi=fig.dpi)
    plt.show()
Beispiel #27
0
def getVoronoiCollection(data,
                         lat_name,
                         lon_name,
                         bmap=None,
                         v_name=None,
                         full_sphere=False,
                         max_v=.3,
                         min_v=-0.3,
                         cmap=matplotlib.cm.get_cmap('jet')):
    '''
    Perform a Spherical Voronoi Tessellation on the input data.

    In the case where the data is restricted to one part of the globe, a polygon will not be returned
    for all objects, as matplotlib polygons won't be able to stretch over half the globe. 

    @param data: Input pandas data frame
    @param lat_name: Name of latitude column
    @param lon_name: Name of longitude column
    @param bmap: Basemap instance used to convert from lat, lon coordinates to projection coordinates
    @param v_name: Name of value column. Use this to color each cell according to a value.
    @param full_sphere: Set to true if the data spans the entire globe. 
                        If false, a fictional point is created during tessellation and 
                        removed later to work around issues when polygons are suppose to 
                        span the over half the globe.
    @param max_v: Specify a maximum value to use when assigning values to the tessellation
    @param min_v: Specify a minimum value to use when assigning values to the tessellation
    @param cmap: Matplotlib color map to use

    @return Matplotlib patch collection of tessellation, scipy.spatial.SphericalVoronoi object, integer index of objects in patch collection.
    '''
    if full_sphere == False:
        test_lat = -1 * np.mean(data[lat_name])
        test_lon = np.mean(data[lon_name]) + 180

        full_data = data
        full_data = pd.concat([
            full_data,
            pd.DataFrame({
                lat_name: test_lat,
                lon_name: test_lon
            },
                         index=[full_data.index[0]])
        ])

        full_data.set_index(np.arange(len(full_data)), inplace=True)

    else:
        full_data = data

    # print(full_data.tail())

    xyz = pd.DataFrame(sphericalToXYZ(full_data[lat_name],
                                      full_data[lon_name]),
                       columns=['x', 'y', 'z'],
                       index=full_data.index)

    if v_name != None:
        full_data = pd.concat(
            [full_data.loc[:, [lat_name, lon_name, v_name]], xyz], axis=1)
    else:
        full_data = pd.concat(
            [full_data.loc[:, [lat_name, lon_name, v_name]], xyz], axis=1)

    unique_index = np.unique(full_data.loc[:, lat_name] +
                             1j * full_data.loc[:, lon_name],
                             return_index=True)[1]

    full_data = full_data.iloc[np.sort(unique_index)]

    voronoi = SphericalVoronoi(full_data.loc[:, ['x', 'y', 'z']])

    voronoi.sort_vertices_of_regions()

    latlon_verts = xyzToSpherical(voronoi.vertices[:, 0],
                                  voronoi.vertices[:, 1], voronoi.vertices[:,
                                                                           2])

    matches = list(
        map(lambda x: find_match(x, voronoi.regions),
            range(len(voronoi.regions))))

    patch_list = []
    patch_index = []

    for i, (region, match, (station, row)) in enumerate(
            zip(voronoi.regions, matches, full_data.iterrows())):

        if full_sphere or (len(matches) - 1) not in match:
            # Keep an index of regions in patchcollection
            patch_index.append(i)

            if bmap != None:
                xy = np.array(
                    bmap(latlon_verts[region, 1], latlon_verts[region, 0])).T
            else:
                xy = np.array(
                    [latlon_verts[region, 1], latlon_verts[region, 0]]).T

            if v_name != None:
                value = row[v_name]
                scaled_value = (value - min_v) / (max_v - min_v)
                if scaled_value > 1:
                    scaled_value = 1.0
                elif scaled_value < 0:
                    scaled_value = 0.0

                poly = Polygon(xy,
                               fill=True,
                               facecolor=cmap(scaled_value),
                               edgecolor=cmap(scaled_value))

            else:
                poly = Polygon(xy, fill=False)

            patch_list.append(poly)

    return matplotlib.collections.PatchCollection(
        patch_list, match_original=True), voronoi, patch_index
Beispiel #28
0
def analyze_protein(protein):
    prot = protein[0]
    chain = protein[1]
    print("Downloading {}{}.".format(prot, chain))

    cmd = "wget https://files.rcsb.org/download/{}.pdb".format(prot)
    proc = Popen(shlex.split(cmd), stdout=DEVNULL, stderr=STDOUT)
    proc.communicate()

    print("Extracting coordinates.")
    cmd = "./pdb_to_xyz.R {}.pdb --chain-id={} -o {}.txt".format(
        prot, chain, prot)
    proc = Popen(shlex.split(cmd), stdout=DEVNULL, stderr=STDOUT)
    proc.communicate()

    print("Removing pdb file.")
    proc = Popen(["rm", "{}.pdb".format(prot)], stdout=DEVNULL, stderr=STDOUT)
    proc.communicate()

    print("Analyzing protein")

    for proj in projections:
        cmd = "./polynomial_invariant {}.txt --names-db=internal --arrow --nb-projections={} --output-diagram={}{}_gl_{}.txt".format(
            prot, proj, prot, chain, proj)
        proc = Popen(shlex.split(cmd), stdout=DEVNULL, stderr=STDOUT)
        proc.communicate()

        name = "{}{}_gl_{}.txt".format(prot, chain, proj)
        origins, origin_types = [], []
        file = open(name, "r")
        next(file)
        me = 0
        checked = []
        vertex_to_index_list = dict()
        edges_to_add = []
        for l in file:
            line = l.strip('\n').split('\t')
            if line[3] != 'UNKNOWN':
                if '*' not in line[3]:
                    origin_types.append(line[3])
                    origins.append(
                        [float(line[0]),
                         float(line[1]),
                         float(line[2])])
                    if line[3] not in checked:
                        vertex_to_index_list[repr(line[3])] = me
                        me += 1

        origins = numpy.array(origins)
        voro = SphericalVoronoi(origins)
        voro.sort_vertices_of_regions()
        for i in range(len(voro.regions)):
            for j in range(i + 1, len(voro.regions)):
                intersect = list(set(voro.regions[i]) & set(voro.regions[j]))
                if intersect:
                    permissable = set(
                        [1, len(voro.regions[i]),
                         len(voro.regions[j])])
                    index_A = [voro.regions[i].index(x) for x in intersect]
                    diff_A = [
                        abs(j - i) for i, j in zip(index_A[:-1], index_A[1:])
                    ]
                    index_B = [voro.regions[j].index(x) for x in intersect]
                    diff_B = [
                        abs(j - i) for i, j in zip(index_B[:-1], index_B[1:])
                    ]
                    # print ("intersect",intersect,"voro[i]",voro.regions[i],"voro[j]",voro.regions[j])
                    # print ("index_A",index_A,"diff_A",diff_A,"index_B",index_B,"diff_B",diff_B)
                    # print ("perm_A",permissable & set(diff_A),"perm_B", permissable & set(diff_B))
                    if permissable & set(diff_A) and permissable & set(diff_B):
                        for k in range(int(len(intersect) / 2)):
                            edges_to_add.append(
                                (vertex_to_index_list[repr(origin_types[i])],
                                 vertex_to_index_list[repr(origin_types[j])]))


# Comment lines 155 - 165 and uncomment lines 169-170 to go to previous version.

# for k in range(int(len(intersect)/2)):
#     edges_to_add.append((vertex_to_index_list[repr(origin_types[i])],vertex_to_index_list[repr(origin_types[j])]))

# print ("len",len(voro.vertices))
        print("Creating graph.")

        g = igraph.Graph(len(origin_types), directed=False)

        origin_types = [
            x.split("|")[0].strip('m').strip('s') for x in origin_types
        ]
        g.vs["label"] = [x for x in origin_types]
        g.add_edges(edges_to_add)
        all_connections = []
        for edge in g.es:
            src = g.vs[edge.source]['label']
            tgt = g.vs[edge.target]['label']
            if (src == '3_1' and tgt != '3_1'):
                all_connections.append((src, tgt))
            elif (src != '3_1' and tgt == '3_1'):
                all_connections.append((tgt, src))

        proj_errors = 0
        error_pairs = []
        for pair in all_connections:

            if theoretical_values[pair[0]][pair[1]] != 1:
                proj_errors += 1
                error_pairs.append(pair)
        try:
            errors = round(proj_errors / len(all_connections), 4)
        except ZeroDivisionError:
            errors = 'NaN'

        edges_between = []
        for edge in g.es:
            src = g.vs[edge.source]['label']
            tgt = g.vs[edge.target]['label']
            if (src == '3_1' and tgt == '2_1'):
                edges_between.append((src, tgt))
            elif (src == '2_1' and tgt == '3_1'):
                edges_between.append((tgt, src))

        if len(edges_between) > 0:
            try:
                interface = round(len(edges_between) / len(all_connections), 4)
            except ZeroDivisionError:
                interface = 'NaN'
        else:
            interface = 'NaN'

        area_31, area_21 = [], []
        all_area_31, all_area_21 = [], []

        # voro_areas = voro.calculate_areas()

        print("voro_areas: ", voro_areas)
        for i in range(len(voro.regions)):
            voronoi_cell = numpy.asarray(
                [list(voro.vertices[x]) for x in voro.regions[i]])
            if origin_types[i] == '3_1':
                sph_pol = SphericalPolygon(voronoi_cell)
                area_31.append(sph_pol.area())
            elif origin_types[i] == '2_1':
                sph_pol = SphericalPolygon(voronoi_cell)

                area_21.append(sph_pol.area())
        all_area_31 = numpy.sum(area_31)
        all_area_21 = numpy.sum(area_21)

        all_graphs.append({
            'n': str(proj),
            'Error': errors,
            'Interface': interface,
            'Protein': prot + chain,
            'Spectrum': len(set(origin_types)),
            'Error Pairs': set(error_pairs),
            'Full Spectrum': set(origin_types),
            'Area  3_1': all_area_31,
            'Area 2_1': all_area_21,
            'Area 2_1/3_1': all_area_21 / all_area_31
        })
Beispiel #29
0
def getVoronoiCollection(data,
                         lat_name,
                         lon_name,
                         bmap=None,
                         v_name=None,
                         full_sphere=False,
                         max_v=.3,
                         min_v=-0.3,
                         cmap=cm.get_cmap('jet'),
                         test_point=None,
                         proj1=None,
                         proj2=None,
                         **kwargs):
    '''
    Perform a Spherical Voronoi Tessellation on the input data.
    In the case where the data is restricted to one part of the globe, a polygon will not be returned
    for all objects, as matplotlib polygons won't be able to stretch over half the globe. 
    @param data: Input pandas data frame
    @param lat_name: Name of latitude column
    @param lon_name: Name of longitude column
    @param bmap: Basemap instance used to convert from lat, lon coordinates to projection coordinates
    @param v_name: Name of value column. Use this to color each cell according to a value.
    @param full_sphere: Set to true if the data spans the entire globe. 
                        If false, a fictional point is created during tessellation and 
                        removed later to work around issues when polygons are suppose to 
                        span the over half the globe.
    @param max_v: Specify a maximum value to use when assigning values to the tessellation
    @param min_v: Specify a minimum value to use when assigning values to the tessellation
    @param cmap: Matplotlib color map to use
    @param test_point: Tuple containing the latitude and longitude of the ficitonal point to used to remove polygons that
                       wrap around the earth. If none, a point is automatically chosen
    @param proj1: PyProj projection of input coordinates
    @param proj2: PyProj projection of sphere
    @return Matplotlib patch collection of tessellation, scipy.spatial.SphericalVoronoi object, integer index of objects in patch collection.
    '''

    data = data.copy()

    if full_sphere == False:
        if test_point == None:
            test_lat = -1 * np.mean(data[lat_name])
            test_lon = np.mean(data[lon_name]) + 180

        else:
            test_lat = test_point[0]
            test_lon = test_point[1]

        full_data = data
        full_data = pd.concat([
            full_data,
            pd.DataFrame({
                lat_name: test_lat,
                lon_name: test_lon
            },
                         index=[full_data.index[0]])
        ])

        full_data.set_index(np.arange(len(full_data)), inplace=True)

    else:
        full_data = data

    # print(full_data.tail())

    if proj1 != None and proj2 != None:
        results = pyproj.transform(proj1, proj2,
                                   full_data[lon_name].as_matrix(),
                                   full_data[lat_name].as_matrix())
        full_data[lon_name] = results[0]
        full_data[lat_name] = results[1]

    xyz = pd.DataFrame(sphericalToXYZ(full_data[lat_name],
                                      full_data[lon_name]),
                       columns=['x', 'y', 'z'],
                       index=full_data.index)

    if v_name != None:
        full_data = pd.concat(
            [full_data.loc[:, [lat_name, lon_name, v_name]], xyz], axis=1)
    else:
        full_data = pd.concat(
            [full_data.loc[:, [lat_name, lon_name, v_name]], xyz], axis=1)

    unique_index = np.unique(full_data.loc[:, lat_name] +
                             1j * full_data.loc[:, lon_name],
                             return_index=True)[1]

    full_data = full_data.iloc[np.sort(unique_index)]

    voronoi = SphericalVoronoi(full_data.loc[:, ['x', 'y', 'z']].as_matrix(),
                               **kwargs)

    voronoi.sort_vertices_of_regions()

    #latlon_verts = xyzToSpherical(voronoi.vertices[:,0],voronoi.vertices[:,1], voronoi.vertices[:,2])

    #if proj1 != None and proj2 != None:
    #    results = pyproj.transform(proj2, proj1, latlon_verts[:,1], latlon_verts[:,0])
    #    latlon_verts[:, 1] = results[0]
    #    latlon_verts[:, 0] = results[1]

    #matches = list(map(lambda x: find_match(x, voronoi.regions), range(len(voronoi.regions))))

    #patch_list = []
    #patch_index = []

    #for i, (region,match,(station,row)) in enumerate(zip(voronoi.regions,matches, full_data.iterrows())):

    #   if full_sphere or (len(matches)-1) not in match:
    # Keep an index of regions in patchcollection
    #       patch_index.append(i)

    #       if bmap != None:
    #           xy = np.array(bmap(latlon_verts[region,1],latlon_verts[region,0])).T
    #       else:
    #           xy = np.array([latlon_verts[region,1],latlon_verts[region,0]]).T

    #       if v_name != None:
    #           value = row[v_name]
    #           scaled_value = (value - min_v) / (max_v - min_v)
    #           if scaled_value > 1:
    #               scaled_value = 1.0
    #           elif scaled_value < 0:
    #               scaled_value = 0.0

    #           poly = Polygon(xy, fill=True,facecolor = cmap(scaled_value),edgecolor=cmap(scaled_value))

    #       else:
    #           poly = Polygon(xy, fill=False)
    #
    #       patch_list.append(poly)

    return voronoi
Beispiel #30
0
 def generate(self, N, iterate=5):
     points = self._samplePoints(N)
     relaxedPoints = self._relaxPoints(points, iterate)
     sv = SphericalVoronoi(relaxedPoints)
     sv.sort_vertices_of_regions()
     return sv