Exemplo n.º 1
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)
Exemplo n.º 2
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()
Exemplo n.º 3
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))
Exemplo n.º 4
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
Exemplo n.º 5
0
 def test_sort_vertices_of_regions(self):
     sv = SphericalVoronoi(self.points)
     unsorted_regions = sv.regions
     sv.sort_vertices_of_regions()
     assert_equal(sorted(sv.regions), sorted(unsorted_regions))
Exemplo n.º 6
0
 def test_old_radius_api_warning(self):
     with assert_warns(DeprecationWarning):
         SphericalVoronoi(self.points, None)
Exemplo n.º 7
0
 def test_old_radius_api(self):
     sv_unit = SphericalVoronoi(self.points, radius=1)
     with suppress_warnings() as sup:
         sup.filter(DeprecationWarning, "`radius` is `None`")
         sv = SphericalVoronoi(self.points, None)
         assert_array_almost_equal(sv_unit.vertices, sv.vertices)
Exemplo n.º 8
0
 def test_equal_area_regions(self, poly):
     points = _generate_polyhedron(poly)
     sv = SphericalVoronoi(points)
     areas = sv.calculate_areas()
     assert_almost_equal(areas, 4 * np.pi / len(points))
Exemplo n.º 9
0
 def setup(self, num_points):
     self.points = generate_spherical_points(num_points)
     self.sv = SphericalVoronoi(self.points, radius=1, center=np.zeros(3))
Exemplo n.º 10
0
 def time_spherical_voronoi_calculation(self, num_points):
     """Perform spherical Voronoi calculation, but not the sorting of
     vertices in the Voronoi polygons.
     """
     SphericalVoronoi(self.points, radius=1, center=np.zeros(3))
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()
Exemplo n.º 12
0
def getVoronoiCollection(data,
                         lat_name,
                         lon_name,
                         voronoi_plot=False,
                         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()

    # BELOW IS ONLY FOR PLOTTING

    if voronoi_plot:

        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 matplotlib.collections.PatchCollection(
            patch_list, match_original=True), voronoi, patch_index
    else:
        return voronoi
Exemplo n.º 13
0
 def test_old_center_api_warning(self):
     with assert_warns(DeprecationWarning):
         sv = SphericalVoronoi(self.points, None, None)
Exemplo n.º 14
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
Exemplo n.º 15
0
 def test_vertices_regions_scaling_invariance(self):
     sv_unit = SphericalVoronoi(self.points)
     sv_scaled = SphericalVoronoi(self.points * 2, 2)
     assert_equal(sv_unit.regions, sv_scaled.regions)
     assert_array_almost_equal(sv_unit.vertices * 2,
                               sv_scaled.vertices)
Exemplo n.º 16
0
 def setup(self, num_points):
     self.points = generate_spherical_points(num_points)
     self.sv = SphericalVoronoi(self.points, radius=1,
                                center=np.zeros(3))
Exemplo n.º 17
0
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
import numpy as np

a = read_text_row("params_027.txt")[:100]
points = angles_to_normals(a)
l = len(points)
points = np.array(points)
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)
# plot generator points
#ax.scatter(points[:, 0], points[:, 1], points[:, 2], c='b')
# plot Voronoi vertices