Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Radial Basis Functions to Interpolate a Function on a Sphere

First, a bit of background:

I am using spherical harmonics as an example of a function on the surface of a sphere like the front spheres in this image:

enter image description here

I produced one of these spheres, coloured according to the value of the harmonic function at points on its surface. I do this first for a very large number of points, so my function is very accurate. I've called this my fine sphere.

enter image description here

Now that I have my fine sphere, I take a relatively small number of points on the sphere. These are the points I wish to interpolate from, the training data, and I call them interp points. Here are my interp points, coloured to their values, plotted on my fine sphere.

enter image description here

Now, the goal of the project is to use these interp points to train a SciPy Radial Basis Function to interpolate my function on the sphere. I was able to do this using:

# 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)

Which produced this interpolation, plotted on the sphere: enter image description here

Hopefully, through this last image, you can see my problem. Notice the line running through the interpolation? This is because the interpolation data has a boundary. The boundary is because I trained the radial basis function using spherical coordinates (boundaries at [0,pi] and [0,2pi]).

rbf = Rbf(interp.phi, interp.theta, harmonic13_coarse)

My goal, and why I'm posting this problem, is to interpolate my function on the surface of the sphere using the x,y,z Cartesian coordinates of the data on the sphere. This way, since spheres don't have boundaries, I won't have this boundary error like I do in spherical coordinates. However, I just can't figure out how to do this.

I've tried simply giving the Rbf function the x,y,z coordinates and the value of the function.

rbf=Rbf(interp.x, interp.y, interp.z, harmonic13_coarse)
interp_values=rbf(fine.x,fine.y,fine.z)

But NumPy throws me a Singular Matrix Error

numpy.linalg.linalg.LinAlgError: singular matrix

Is there any way for me to give Rbf my data sites in Cartesian coordinates, with the function values at each site and have it behave like it does with spherical coordinates but without that boundaries? From the Rbf documentation, there is the attribute norm for defining a different distance norm, could I have to use a spherical distance to get this to work?

I'm pretty much stumped on this. Let me know if you have any ideas for interpolating my function on a sphere without the boundaries of spherical coordinates.

Here is my code in full:

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()
like image 378
Jesse Avatar asked Aug 06 '14 20:08

Jesse


2 Answers

The boundary you see is because you are mapping a closed surface (S2) to an open one (R2). One way or another, you will have boundaries. The local properties of the manifolds are compatible, so it works for most of the sphere, but not the global, you get a line.

The way around it is to use an atlas instead of a single chart. An atlas is a collection of overlapping charts. In the overlapping region, you need to define weights, a smooth function that goes from 0 to 1 on each chart. (Sorry, probably differential geometry was not what you were expecting to hear).

If you don't want to go all the way here, you can notice that your original sphere has an equator where the variance is minimal. You can then rotate your fine sphere and make it coincide with the line. It doesn't solve your problem, but it can certainly mitigate it.

like image 78
Davidmh Avatar answered Nov 13 '22 18:11

Davidmh


You can change the standard distance:

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

by the sphere distance (see, for instance, this question Haversine Formula in Python (Bearing and Distance between two GPS points)).

like image 45
J.L. Bravo Avatar answered Nov 13 '22 17:11

J.L. Bravo