首先,有点背景知识:
我使用球面谐波作为球体表面上的函数示例,如此图像中的前球体:
我制作了这些球体中的一个,根据其表面上的点处的谐波函数的值着色。我首先做了很多点,所以我的功能非常准确。我称之为我的fine
球体。
现在我拥有了fine
球体,我在球体上采用了相对较少的点数。这些是我希望插入的点,训练数据,我称之为interp
点。以下是我的interp
点,颜色与其值相对应,绘制在我的fine
范围内。
现在,该项目的目标是使用这些interp
点来训练SciPy Radial Basis Function在球体上插入我的函数。我能够这样做:
# Train the interpolation using interp coordinates
rbf = Rbf(interp.phi, interp.theta, harmonic13_coarse)
# The result of the interpolation on fine coordinates
interp_values = rbf(fine.phi, fine.theta)
生成此插值,绘制在球体上:
希望通过最后一张图片,您可以看到我的问题。注意通过插值的线?这是因为插值数据具有边界。边界是因为我使用球面坐标([0,pi]和[0,2pi]处的边界)训练了径向基函数。
rbf = Rbf(interp.phi, interp.theta, harmonic13_coarse)
我的目标,以及我发布此问题的原因,是使用球体上数据的x,y,z笛卡尔坐标在球体表面上插入我的函数。这样,由于球体没有边界,我不会像在球坐标中那样出现这个边界误差。但是,我无法弄清楚如何做到这一点。
我尝试过简单地给出Rbf函数的x,y,z坐标和函数的值。
rbf=Rbf(interp.x, interp.y, interp.z, harmonic13_coarse)
interp_values=rbf(fine.x,fine.y,fine.z)
但NumPy却给我一个奇异的矩阵错误
numpy.linalg.linalg.LinAlgError: singular matrix
我有没有办法让Rbf我的数据站点在笛卡尔坐标系中,每个站点都有函数值,并且它的行为与球面坐标一样,但没有这个边界?从Rbf文档中,有用于定义不同距离范数的属性norm
,我是否必须使用球形距离才能使其工作?
我对此非常感激不已。如果您有任何关于在球体上插入我的函数而没有球坐标边界的想法,请告诉我。
以下是我的完整代码:
import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy import special
from scipy.interpolate import Rbf
from collections import namedtuple
from mayavi import mlab
# Nice aliases
pi = np.pi
cos = np.cos
sin = np.sin
# Creating a sphere in Cartesian and Sphereical
# Saves coordinates as named tuples
def coordinates(r, n):
phi, theta = np.mgrid[0:pi:n, 0:2 * pi:n]
Coor = namedtuple('Coor', 'r phi theta x y z')
r = r
x = r * sin(phi) * cos(theta)
y = r * sin(phi) * sin(theta)
z = r * cos(phi)
return Coor(r, phi, theta, x, y, z)
# Creating a sphere
# fine is coordinates on a fine grid
# interp is coordinates on coarse grid for training interpolation
fine = coordinates(1, 100j)
interp = coordinates(1, 5j)
# Defining finection to colour sphere
# Here we are using a spherical harmonic
def harmonic(m, n, theta, phi):
return special.sph_harm(m, n, theta, phi).real
norm = colors.Normalize()
# One example of the harmonic function, for testing
harmonic13_fine = harmonic(1, 3, fine.theta, fine.phi)
harmonic13_coarse = harmonic(1, 3, interp.theta, interp.phi)
# Train the interpolation using interp coordinates
rbf = Rbf(interp.phi, interp.theta, harmonic13_coarse)
# The result of the interpolation on fine coordinates
interp_values = rbf(fine.phi, fine.theta)
rbf=Rbf(interp.x, interp.y, interp.z, harmonic13_coarse)
interp_values=rbf(fine.x,fine.y,fine.z)
#Figure of harmoinc function on sphere in fine cordinates
#Points3d showing interpolation training points coloured to their value
mlab.figure()
vmax, vmin = np.max(harmonic13_fine), np.min(harmonic13_fine)
mlab.mesh(fine.x, fine.y, fine.z, scalars=harmonic13_fine, vmax=vmax, vmin=vmin)
mlab.points3d(interp.x, interp.y, interp.z, harmonic13_coarse,
scale_factor=0.1, scale_mode='none', vmax=vmax, vmin=vmin)
#Figure showing results of rbf interpolation
mlab.figure()
vmax, vmin = np.max(harmonic13_fine), np.min(harmonic13_fine)
mlab.mesh(fine.x, fine.y, fine.z, scalars=interp_values)
# mlab.points3d(interp.x, interp.y, interp.z, scalars, scale_factor=0.1, scale_mode='none',vmax=vmax, vmin=vmin)
mlab.show()
答案 0 :(得分:4)
您看到的边界是因为您正在将闭合曲面(S2)映射到开放曲面(R2)。不管怎样,你都会有界限。歧管的局部属性是兼容的,因此它适用于大多数球体,但不适用于全局,你得到一条线。
绕过它的方法是使用地图集而不是单个图表。地图集是重叠图表的集合。在重叠区域中,您需要定义权重,即每个图表上从0到1的平滑函数。 (对不起,差异几何可能不是你期望听到的)。
如果你不想一直走到这里,你可以注意到你的原始球体有一个赤道,方差最小。然后,您可以旋转精细球体并使其与线条重合。它并没有解决你的问题,但它肯定可以缓解它。
答案 1 :(得分:4)
您可以更改标准距离:
def euclidean_norm(x1, x2):
return np.sqrt( ((x1 - x2)**2).sum(axis=0) )
按球距离(例如,请参阅此问题Haversine Formula in Python (Bearing and Distance between two GPS points))。