Python 使用径向基函数插值球面上的函数

Python 使用径向基函数插值球面上的函数,python,numpy,scipy,interpolation,Python,Numpy,Scipy,Interpolation,首先,有一点背景: 我使用球谐函数作为球体表面函数的示例,如图中的前球体: 我制作了其中一个球体,根据其表面上点的调和函数的值着色。我首先对大量的点做这个,所以我的函数非常精确。我把它称为我的finesphere 现在我有了fine球体,我在球体上取了相对较少的点。这些是我希望从训练数据中插值的点,我称它们为interp点。这是我的interp点,按它们的值着色,绘制在我的fine球体上 现在,该项目的目标是使用这些interp点来训练a,在球体上插值我的函数。我可以通过以下方式完成此操作

首先,有一点背景:

我使用球谐函数作为球体表面函数的示例,如图中的前球体:

我制作了其中一个球体,根据其表面上点的调和函数的值着色。我首先对大量的点做这个,所以我的函数非常精确。我把它称为我的
fine
sphere

现在我有了
fine
球体,我在球体上取了相对较少的点。这些是我希望从训练数据中插值的点,我称它们为
interp
点。这是我的
interp
点,按它们的值着色,绘制在我的
fine
球体上

现在,该项目的目标是使用这些
interp
点来训练a,在球体上插值我的函数。我可以通过以下方式完成此操作:

# 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]处的边界)训练径向基函数

我的目标,以及我为什么要发布这个问题,是使用球体上数据的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()

您看到的边界是因为您正在将闭合曲面(S2)映射到开放曲面(R2)。不管怎样,你都会有界限。流形的局部属性是兼容的,所以它适用于大多数球体,但不适用于全局,你可以得到一条线

解决这个问题的方法是使用一个地图集,而不是单一的图表。地图集是重叠图表的集合。在重叠区域中,需要定义权重,这是一个平滑函数,在每个图表上从0到1。(对不起,可能微分几何不是您所期望听到的)


如果你不想一直走到这里,你可以注意到你的原始球体有一个赤道,在那里方差最小。然后可以旋转精细球体,使其与直线重合。它不能解决您的问题,但肯定可以缓解问题。

您可以更改标准距离:

def euclidean_norm(x1, x2):
    return np.sqrt( ((x1 - x2)**2).sum(axis=0) )
通过球体距离(例如,请参见此问题)

def euclidean_norm(x1, x2):
    return np.sqrt( ((x1 - x2)**2).sum(axis=0) )