3

我正在尝试创建一个图来显示水平面上的温度梯度。我能够降低颜色,但它没有按照我需要的方式进行插值。这个问题有助于创建情节。绘制绘图时,似乎这些点的权重不均等。就是图表当前的样子。它应该看起来像彩条,因为顶部两点是 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()
4

2 回答 2

6

扩展我之前的评论:

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

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

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

举个例子:

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

在此处输入图像描述 在此处输入图像描述

两者之间的唯一区别只是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

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

于 2013-07-10T18:59:30.310 回答
2

或者,如果您安装了 matplolib 1.3.0,您可以对数据进行三角测量并使用精炼/平滑函数: matplotlib.tri.UniformTriRefiner (它应该为任何a数据提供平滑的轮廓,并且对于xy的线性函数是精确的)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import matplotlib.cm as cm

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

    triang = mtri.Triangulation(x, y)
    refiner = mtri.UniformTriRefiner(triang)
    tri_refi, z_test_refi = refiner.refine_field(a, subdiv=4)

    plt.figure()
    plt.gca().set_aspect('equal')
    levels = np.arange(23.4, 23.7, 0.025)
    cmap = cm.get_cmap(name='terrain')
    plt.tricontourf(tri_refi, z_test_refi, levels=levels, cmap=cmap)
    plt.colorbar()

    plt.title("Triangulated")
    plt.show()

main() 
于 2013-08-19T21:13:55.033 回答