带插值的 Matplotlib 二维图

use*_*081 3 python matplotlib

我正在尝试创建一个图来显示水平表面上的温度梯度。我能够降低颜色,但它并没有按照我需要的方式进行插值。这个问题有助于创建情节。似乎在生成情节时这些点的权重不同。是图形当前的外观。它应该看起来像颜色条,因为顶部的两个点是 23.7,底部的两个点是 23.4。我使用的代码是: 在此处输入图片说明

   xi, yi = np.linspace(xm, xM, 500), np.linspace(ym, yM, 500)
   xi, yi = np.meshgrid(xi, yi)
   xo=[0, 0, 2, 2]
   yo=[0, 2, 0, 2]
   ao=[23.4, 23.7, 23.4, 23.7]
   rbf = scipy.interpolate.Rbf(xo, yo, ao, function='linear')
   ai = rbf(xi, yi)

   plt.xlabel('X')
   plt.ylabel('Y')

   plt.imshow(ai, vmin=am, vmax=aM, origin='lower', extent=[xm, xM, ym, yM])

   plt.scatter(xo, yo, c=ao)
   plt.colorbar()
   plt.show()
Run Code Online (Sandbox Code Playgroud)

Joe*_*ton 6

扩展我之前的评论:

发生的事情是由于您的a-values 的绝对值比xandy值大约 10 倍。

在求解适当的权重时,这会导致数值稳定性问题。Scipy 可能应该做一些健全性检查并“白化”(又名重新缩放)输入数据,但事实并非如此。

由于权重不正确,内插值低于最小输入a值(线性 RBF 不会发生这种情况)。正如@user1767344 所注意到的,这会导致您指定的vminvmax值“剪裁”网格。我在下面显示“未剪辑”版本,但如果您指定类似的vminvmax,您将看到与原始示例相同的结果。

举个例子:

import numpy as np
import scipy.interpolate
import matplotlib.pyplot as plt

def main():
    x = np.array([0, 0, 2, 2])
    y = np.array([0, 2, 0, 2])
    a = np.array([23.4, 23.7, 23.4, 23.7])
    xi, yi = np.mgrid[x.min():x.max():500j, y.min():y.max():500j]

    a_orig = normal_interp(x, y, a, xi, yi)
    a_rescale = rescaled_interp(x, y, a, xi, yi)

    plot(x, y, a, a_orig, 'Not Rescaled')
    plot(x, y, a, a_rescale, 'Rescaled')
    plt.show()

def normal_interp(x, y, a, xi, yi):
    rbf = scipy.interpolate.Rbf(x, y, a)
    ai = rbf(xi, yi)
    return ai

def rescaled_interp(x, y, a, xi, yi):
    a_rescaled = (a - a.min()) / a.ptp()
    ai = normal_interp(x, y, a_rescaled, xi, yi)
    ai = a.ptp() * ai + a.min()
    return ai

def plot(x, y, a, ai, title):
    fig, ax = plt.subplots()

    im = ax.imshow(ai.T, origin='lower',
                   extent=[x.min(), x.max(), y.min(), y.max()])
    ax.scatter(x, y, c=a)

    ax.set(xlabel='X', ylabel='Y', title=title)
    fig.colorbar(im)

main()      
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明 在此处输入图片说明

两者之间的唯一区别只是a在 0 和 1 之间线性重新调整输入和输出值:

def normal_interp(x, y, a, xi, yi):
    rbf = scipy.interpolate.Rbf(x, y, a)
    ai = rbf(xi, yi)
    return ai

def rescaled_interp(x, y, a, xi, yi):
    a_rescaled = (a - a.min()) / a.ptp()
    ai = normal_interp(x, y, a_rescaled, xi, yi)
    ai = a.ptp() * ai + a.min()
    return ai
Run Code Online (Sandbox Code Playgroud)

因为它是一种 2D 插值方法,所以结果并不完全“像颜色条”。如果您愿意,您可以只使用一维插值并平铺结果。或者,在这种情况下,简单的三角插值方法(例如griddata)是一个不错的选择,并且应该给出与一维结果相同的结果。(缺点是在其他情况下它不会“平滑”,但这始终是一种权衡。)