是否可以为scipy.spatial.Voronoi
图表着色? I know it is.
但现在我的目标是根据色标为每个细胞着色以表示物理量。
如下图所示(PRL 107,155704(2011)):
我还想知道是否可以计算每个单元格的面积,因为它是我想要计算的数量
答案 0 :(得分:8)
实际上,您提供的link提供了对Voronoi图进行着色所需的代码。为了为每个单元格指定一个表示物理量的颜色,您需要使用Map values to colors in matplotlib中显示的方法将此物理量的值映射到标准化的色彩映射。
例如,如果我想为每个单元格指定一个与数量相对应的颜色'速度':
import numpy as np
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi, voronoi_plot_2d
# generate data/speed values
points = np.random.uniform(size=[50, 2])
speed = np.random.uniform(low=0.0, high=5.0, size=50)
# generate Voronoi tessellation
vor = Voronoi(points)
# find min/max values for normalization
minima = min(speed)
maxima = max(speed)
# normalize chosen colormap
norm = mpl.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
mapper = cm.ScalarMappable(norm=norm, cmap=cm.Blues_r)
# plot Voronoi diagram, and fill finite regions with color mapped from speed value
voronoi_plot_2d(vor, show_points=True, show_vertices=False, s=1)
for r in range(len(vor.point_region)):
region = vor.regions[vor.point_region[r]]
if not -1 in region:
polygon = [vor.vertices[i] for i in region]
plt.fill(*zip(*polygon), color=mapper.to_rgba(speed[r]))
plt.show()
)
scipy.spatial.Voronoi
允许您访问每个单元格的顶点,您可以订购并应用shoelace formula。我还没有测试输出足以知道Voronoi算法给出的顶点是否已经订购。但如果没有,你可以使用点积来获得每个顶点的矢量和一些参考矢量之间的角度,然后使用这些角度对顶点进行排序:
# ordering vertices
x_plus = np.array([1, 0]) # unit vector in i direction to measure angles from
theta = np.zeros(len(vertices))
for v_i in range(len(vertices)):
ri = vertices[v_i]
if ri[1]-self.r[1] >= 0: # angle from 0 to pi
cosine = np.dot(ri-self.r, x_plus)/np.linalg.norm(ri-self.r)
theta[v_i] = np.arccos(cosine)
else: # angle from pi to 2pi
cosine = np.dot(ri-self.r, x_plus)/np.linalg.norm(ri-self.r)
theta[v_i] = 2*np.pi - np.arccos(cosine)
order = np.argsort(theta) # returns array of indices that give sorted order of theta
vertices_ordered = np.zeros(vertices.shape)
for o_i in range(len(order)):
vertices_ordered[o_i] = vertices[order[o_i]]
# compute the area of cell using ordered vertices (shoelace formula)
partial_sum = 0
for i in range(len(vertices_ordered)-1):
partial_sum += vertices_ordered[i,0]*vertices_ordered[i+1,1] - vertices_ordered[i+1,0]*vertices_ordered[i,1]
partial_sum += vertices_ordered[-1,0]*vertices_ordered[0,1] - vertices_ordered[0,0]*vertices_ordered[-1,1]
area = 0.5 * abs(partial_sum)