Wednesday, 23 November 2022

Bed-o-nails interpolation with scipy's RBFInterpolator

I'm trying to interpolate a 2D data set with RBFInterpolator. The purpose of the interpolation is to convert the data set into a continuous function that can then be sampled between the points. Unfortunately, I'm getting a bed of nails result.

This is the dataset enter image description here

This is the interpolator shown as a pcolormesh (see vertical lines for bed of nails) enter image description here

These are two plots showing the data and the interpolator along the x axis (0, pi). In these the bed of nails nature of the interpolator is most clear. enter image description here enter image description here

Here is all of my code verbatim (sorry if it's messy). I'm using the RBFInterpolator defaults, and I'm not setting the shape parameter at all.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import RBFInterpolator
import seaborn as sns

if __name__ == "__main__":
    # get the two files and combine into one dataframe
    cols = ["a_test", "e_test", "a", "e", "lop", "dlop_dt"]
    large_dlop = pd.read_csv('epsilon-ring/all-to-all/dlop-dt.dat', delimiter='\t', names=cols)
    small_dlop = pd.read_csv('epsilon-ring/small-dlop/dlop-dt.dat', delimiter='\t', names=cols)
    df = pd.concat([large_dlop, small_dlop]).reset_index(drop=True)
    # go through and fit each line
    a_test = np.unique(df['a_test'])
    a = np.unique(df['a'])
    lop_grid = np.linspace(0., np.pi, num=1000)
    a_grid = np.linspace(a.min(), a.max(), num=50)
    lop_mgrid, a_mgrid = np.meshgrid(lop_grid, a_grid)
    grid = np.concatenate((lop_mgrid.flatten()[:,None], a_mgrid.flatten()[:,None]), axis=1)
    colors = sns.color_palette()
    interpolants = []
    for i in range(a_test.shape[0]):
        # select semi-major axis
        select_test = df['a_test'] == a_test[i]
        # intepolation
        points = np.concatenate((df[select_test]['lop'].to_numpy()[:,None], \
                                 df[select_test]['a'].to_numpy()[:,None]), axis=1)
        rbf = RBFInterpolator(points, df[select_test]['dlop_dt'])
        interpolants.append(rbf)
        # plot points
        fig = plt.figure()
        ax = plt.axes(projection='3d')
        ax.scatter3D(df[select_test]['lop'], df[select_test]['a'], df[select_test]['dlop_dt'])
        ax.set_xlabel(r'$\varpi$')
        ax.set_ylabel(r'$a$')
        ax.set_zlabel(r'$\dot{\varpi}$')
        plt.tight_layout()
        plt.show()
        # plot colormesh
        fig, ax = plt.subplots()
        pc = ax.pcolormesh(lop_grid, a_grid, rbf(grid).reshape(lop_mgrid.shape), shading='gouraud')
        ax.set_xlabel(r'$\varpi$')
        ax.set_ylabel(r'$a$')
        plt.colorbar(pc, label=r'$\dot{\varpi}$')
        plt.tight_layout()
        plt.show()
        # check if interpolant actually interpolates well
        colors = sns.color_palette()
        for j in range(a.shape[0]):
            select_disk = df[select_test]['a'] == a[j]
            small_grid = np.concatenate((lop_grid[:,None], a[j]*np.ones(lop_grid.shape)[:,None]), axis=1)
            plt.scatter(df[select_test][select_disk]['lop'], df[select_test][select_disk]['dlop_dt'], color=colors[0], label='data')
            plt.plot(lop_grid, rbf(small_grid), color=colors[1], label='interp')
            plt.xlabel(r'$\varpi$')
            plt.ylabel(r'$\dot{\varpi}$')
            plt.legend()
            plt.tight_layout()
            plt.show()

How do I get the RBFInterpolator to interpolate the function better? What is causing this wild interpolation result? The underlying data is smooth, though kinda steep close to zero.

EDIT:

I still haven't figured out why RBFInterpolator is giving me poor results. I've tried most of the different kernels ('linear', 'cubic', 'thin_plate_spline', 'gaussian', and 'multiquadric') with and without adjusting the smoothing or epsilon parameter (depending on if the kernel is compatible with smoothing or the shape parameter). I still haven't gotten a satisfactory interpolation.

Fortunately, it appears that scipy.interpolate.griddata is able to interpolate the data just fine.

Here are some plots of the griddata interpolation:

Data + contour3D from griddata interpolation enter image description here

pcolormesh of the griddata interpolation enter image description here

1D plots comparing the RBF to the griddata enter image description here enter image description here

I'd still love to know what's wrong with the RBFInterpolator. I've noticed that the RBFInterpolator seems to be trying to return to some function between the interpolation points (i.e. look at the last two plots, the 'bed' in the bed-of-nails interpolation result is the same for both plots).



from Bed-o-nails interpolation with scipy's RBFInterpolator

No comments:

Post a Comment