单位球体表面区域上点的随机样本
Random sample of points on a region of the surface of a unit sphere
我需要生成分布在球体表面 区域 上的点的随机样本。 This answer 给出了一个优雅的方法来对球体的整个表面进行采样:
def sample_spherical(npoints, ndim=3):
vec = np.random.randn(ndim, npoints)
vec /= np.linalg.norm(vec, axis=0)
return vec
(vec
returns (x, y, z)
坐标) 结果:
我需要将采样限制在一个矩形区域。该区域由中心值和长度定义,例如:
- 中心坐标,例如:
(ra_0, dec_0) = (34, 67)
- 边长,例如:
(ra_l, dec_l) = (2, 1)
其中 (ra_0, dec_0)
是 equatorial system 中的坐标,长度以度为单位。
我可以按以下方式使用上述函数:使用大 npoints
调用它,将返回的 (x, y, z)
值转换为赤道系统,拒绝定义区域之外的值,然后重复直到达到所需的样本数。不过,我觉得必须有一种更优雅的方法来实现这一点。
假设您想从 'rectangle' 中随机均匀地采样点 :
- 随机均匀采样z坐标
- 随机均匀采样经度
import numpy as np
rad = np.pi / 180
def sample_spherical_rect(npoints, ra_0, dec_0, ra_l, dec_l):
lon_min = (dec_0 - .5 * dec_l) * rad
lon_delta = dec_l * rad
z_min = np.sin((ra_0 - .5 * ra_l) * rad)
z_max = np.sin((ra_0 + .5 * ra_l) * rad)
z_delta = z_max - z_min
z = z_min + np.random.rand(npoints) * z_delta
lat = np.arcsin(z)
cos_lat = np.cos(lat)
lon = lon_min + np.random.rand(npoints) * lon_delta
x = np.cos(lon) * cos_lat
y = np.sin(lon) * cos_lat
return np.array([x,y,z])
说明:单位球面的点具有以下性质:
每个笛卡尔坐标轴 x,y,z 本身在 [-1, 1]
中是一致的
鉴于
- x = cos(lon) cos(lat)
- y = sin(lon) cos(lat)
- z = 余弦(纬度)
lon 在 [0, 2pi] 内是均匀的。
lon 和 z 在统计上是独立的。
由于球坐标(lat/lon)中的一个矩形等价于mixed坐标(z/lon)中的一个矩形,所以只需要均匀采样在您想要的范围内随机在 (z / lon) 中,然后将 z 和 lon 转换为 x 和 y。
进一步说明
由于从单位球体中采样的点 (x,y,z) 在每个笛卡尔坐标中具有均匀分布似乎并不明显:
由a <= z <= b
(-1 <= a < b <= 1
)界定的单位球体的切片的表面由(我可以输入乳胶数学东西吗?所以?):
A = int_{arcsin(a)}^{arcsin(b)} d[theta] int_0^{2 pi} d[phi] cos(theta) # cos(theta) is the Jacobian
= 2 pi [sin(theta)]_{theta=arcsin(a)}^{theta=arcsin(b)}
= 2 pi * (b - a)
我需要生成分布在球体表面 区域 上的点的随机样本。 This answer 给出了一个优雅的方法来对球体的整个表面进行采样:
def sample_spherical(npoints, ndim=3):
vec = np.random.randn(ndim, npoints)
vec /= np.linalg.norm(vec, axis=0)
return vec
(vec
returns (x, y, z)
坐标) 结果:
我需要将采样限制在一个矩形区域。该区域由中心值和长度定义,例如:
- 中心坐标,例如:
(ra_0, dec_0) = (34, 67)
- 边长,例如:
(ra_l, dec_l) = (2, 1)
其中 (ra_0, dec_0)
是 equatorial system 中的坐标,长度以度为单位。
我可以按以下方式使用上述函数:使用大 npoints
调用它,将返回的 (x, y, z)
值转换为赤道系统,拒绝定义区域之外的值,然后重复直到达到所需的样本数。不过,我觉得必须有一种更优雅的方法来实现这一点。
假设您想从 'rectangle' 中随机均匀地采样点 :
- 随机均匀采样z坐标
- 随机均匀采样经度
import numpy as np
rad = np.pi / 180
def sample_spherical_rect(npoints, ra_0, dec_0, ra_l, dec_l):
lon_min = (dec_0 - .5 * dec_l) * rad
lon_delta = dec_l * rad
z_min = np.sin((ra_0 - .5 * ra_l) * rad)
z_max = np.sin((ra_0 + .5 * ra_l) * rad)
z_delta = z_max - z_min
z = z_min + np.random.rand(npoints) * z_delta
lat = np.arcsin(z)
cos_lat = np.cos(lat)
lon = lon_min + np.random.rand(npoints) * lon_delta
x = np.cos(lon) * cos_lat
y = np.sin(lon) * cos_lat
return np.array([x,y,z])
说明:单位球面的点具有以下性质:
每个笛卡尔坐标轴 x,y,z 本身在 [-1, 1]
中是一致的鉴于
- x = cos(lon) cos(lat)
- y = sin(lon) cos(lat)
- z = 余弦(纬度)
lon 在 [0, 2pi] 内是均匀的。
lon 和 z 在统计上是独立的。
由于球坐标(lat/lon)中的一个矩形等价于mixed坐标(z/lon)中的一个矩形,所以只需要均匀采样在您想要的范围内随机在 (z / lon) 中,然后将 z 和 lon 转换为 x 和 y。
进一步说明
由于从单位球体中采样的点 (x,y,z) 在每个笛卡尔坐标中具有均匀分布似乎并不明显:
由a <= z <= b
(-1 <= a < b <= 1
)界定的单位球体的切片的表面由(我可以输入乳胶数学东西吗?所以?):
A = int_{arcsin(a)}^{arcsin(b)} d[theta] int_0^{2 pi} d[phi] cos(theta) # cos(theta) is the Jacobian
= 2 pi [sin(theta)]_{theta=arcsin(a)}^{theta=arcsin(b)}
= 2 pi * (b - a)