不均匀采样角度值的二维插值/平滑

时间:2014-11-30 20:41:36

标签: python math numpy scipy interpolation

我有一些数据由不均匀采样的2D空间位置组成,其中每个 x,y 坐标在0到2pi之间具有相关的相位值 theta 。我希望能够将 theta 值插入到常规 x,y 网格中。数据是简并的,因为相同(或非常接近)的 x,y 位置可能与多个相位值相关联,反之亦然 theta 的值,所以严格来说,这是一个平滑问题,而不是直接插值。

我已经简短地尝试过scipy的径向基函数,但由于 theta 值的不连续性来自2pi - >,这些会产生令人讨厌的边缘效应。 0

这是一个玩具示例(阶段的真实空间分布很麻烦):

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colorbar
from matplotlib.colors import Normalize
from scipy import interpolate

# randomly sampled spatial locations
x, y = np.random.uniform(-1, 1, size=(2, 1000))
# theta varies smoothly with location apart from the singularity at 0, 0
z = np.arctan2(x, y) % (2 * np.pi)

# smooth with a simple linear RBF
rbf = interpolate.Rbf(x, y, z, function='linear', smooth=0.1)

# resample on a finer grid
xi, yi = np.mgrid[-1:1:100j, -1:1:100j].reshape(2, -1)
zi = rbf(xi, yi) % (2 * np.pi)

# plotting
fig, ax = plt.subplots(1, 1, subplot_kw={'aspect': 'equal'})
ax.hold(True)
norm = Normalize(0, 2 * np.pi)
im = ax.imshow(zi.reshape(100, 100).T, extent=(-1, 1, -1, 1),
               origin='lower', cmap=plt.cm.hsv, norm=norm)
sc = ax.scatter(x, y, s=30, c=z, cmap=im.cmap, norm=norm)
cax, kw = colorbar.make_axes_gridspec(ax)
cb = plt.colorbar(im, cax=cax, **kw)
ax.set_xlabel(r'$X_0$', fontsize='x-large')
ax.set_ylabel(r'$Y_0$', fontsize='x-large')
cb.set_ticks(np.arange(0, 2.1*np.pi, np.pi/2.))
cb.set_ticklabels([r'$0$', r'$\frac{\pi}{2}$', r'$\pi$',
                   r'$\frac{3\pi}{2}$', r'$2\pi$'])
cb.set_label(r'$\theta$', fontsize='x-large')
cb.ax.tick_params(labelsize='x-large')
plt.show()

enter image description here

这样插入角度量的好方法是什么? scipy有没有内置的插值方法可以很好地处理角度,还是我必须自己编写?

1 个答案:

答案 0 :(得分:2)

我现在觉得很蠢!

答案非常简单 - this answer on MathOverflow让我陷入困境。如果我从极坐标空间转换为笛卡尔坐标空间,然后独立插入向量的x和y分量,则不连续性没有问题:

x, y = np.random.uniform(-1, 1, size=(2, 1000))
z = np.arctan2(y, x) % (2*np.pi)

# convert from polar --> cartesian
u, v = np.cos(z), np.sin(z)

# interpolate x and y components separately
rbf_u = interpolate.Rbf(x, y, u, function='linear', smooth=0.1)
rbf_v = interpolate.Rbf(x, y, v, function='linear', smooth=0.1)
xi, yi = np.mgrid[-1:1:100j, -1:1:100j].reshape(2, -1)
ui = rbf_u(xi, yi)
vi = rbf_v(xi, yi)

# convert from cartesian --> polar
zi = np.arctan2(ui, vi) % (2*np.pi)

enter image description here

如果有一种方法可以避免在x和y组件上执行两个单独的插值,那么性能会很好,但我真的没有办法解决这个问题。