scipy 插值平面的语法(Python)

k10s72fa  于 2022-12-04  发布在  Python
关注(0)|答案(3)|浏览(143)

我有一个函数D(x,y,z),我想在其中评估(通过插值)z,y和z轴内的平面。也就是说,我想我的插值输出是一个2D平面,保持其中一个固定值,例如D(x,y,0)。
我已经通过scipy创建了一个插值函数,使用一些给定的D值,D_values,作为我的输入值x,y,z。

from scipy.interpolate import RegularGridInterpolator as rgi   
D_interp=rgi((x_positions,y_positions,z_positions), D_values)

现在我可以通过调用

D_interpolated=D_interp(xi,yi,zi)

我知道如何计算各个点的值,但是如何插值平面呢?例如,在我的例子中,D_values的大小为345x155x303,我想沿着z轴插值345x155个平面,对应于x和y输入值,在z=0、z=1、z=2等位置。
我尝试的解决方案是将x_positions,y_positions向量分别馈入D_interp,保持z固定,但这只是得到一组在特定位置求值的D值,而不是像我实际想要的平面输出那样组织成网格。

Plane=D_interp(x_positions,y_positions,0)

所以我不太确定调用该函数以获得平面输出的语法。
任何帮助都感激不尽
谢谢你,

kb5ga3dv

kb5ga3dv1#

在numpy和scipy中,组合多个不同大小的数组(对应于不同的维数)的典型方法是使用broadcasting。下面是一个示例问题来说明应用程序:

x_positions = np.linspace(0, 10, 101)
y_positions = np.linspace(-10, 10, 201)
z_positions = np.linspace(-5, 5, 101)
D_values = np.sin(2 * np.pi * x_positions[:, None, None] * y_positions[:, None] / 100) + np.cos(2 * np.pi * y_positions[:, None] * z_positions / 50)

这类似于您在问题中描述的D_values数组,其中不同方向的每个bin对应于*_positions数组。将y_positions转换为(201, 1)形状的数组,将z_positions转换为(101,)形状的数组。结果是D_values(101, 201, 101)形状的数组。输入数组的整形版本未复制任何数据!
您可以使用创建D_values样本时使用的相同方法调用插值器。

D_interp = rgi((x_positions, y_positions, z_positions), D_values)

假设您要修复z = 0,scipy所要求的只是输入一起广播,标量广播所有内容,因此您可以

x_interp = np.linspace(0.05, 0.95, 200)
y_interp = np.linspace(-9.95, 9.95, 400)
z_interp = 0
D_xy_interp = D_interp((x_interp[:, None], y_interp, z_interp))

与创建网格相比,这样做的好处是不必复制任何数据,也不必创建额外的200 x400输入数组。另一个好处是可以更好地控制输出。在本例中,D_xy_interp的形状为(len(x_interp), len(y_interp))。这是因为通常情况下,输出的形状将是输入的广播形状。当我们创建D_values时,您可以看到它,在这里也可以看到。由于0是标量,它对形状没有影响。但我也可以创建一个(400, 200)形状的数组:

D_interp((x_interp, y_interp[:, None], z_interp))

或者甚至是(100, 4, 100, 2)形状的阵列:

D_interp((x_interp.reshape(-1, 2), y_interp.reshape(-1, 4, 1, 1), z_interp))

无论哪种情况,我们都要验证插值器是否完成了它的工作,我们可以将插值值与创建D_values的函数的更精细采样进行比较:

D_xy_values = np.sin(2 * np.pi * x_interp[:, None] * y_interp / 100) + np.cos(2 * np.pi * y_interp * z_interp / 50)

fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
ax.plot_surface(x_interp[:, None], y_interp, D_xy_interp, label='Interp')
ax.plot_surface(x_interp[:, None], y_interp, D_xy_values, label='Values')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()

目前,您似乎无法将图例添加到3D图中:
x1c 0d1x。
这两个图实际上是无法区分的。使用默认的颜色循环仪,当您旋转它时,您将看到表面从蓝色变为橙子。下面是一个分析验证:

>>> np.sqrt(np.mean((D_xy_values - D_xy_interp)**2))
4.707625623185639e-05
b4lqfgs4

b4lqfgs42#

若要使用SciPy中的RegularGridInterpolator类别评估平面,您可以使用interpolator对象的__call__方法,并将固定维度的值指定为保留字参数。
例如,要在z=0处沿着z轴插入平面,可以使用以下代码:

from scipy.interpolate import RegularGridInterpolator as rgi

# Define the input values for the x, y, and z dimensions
x_positions = ...
y_positions = ...
z_positions = ...

# Define the values of the function D at each point in the grid
D_values = ...

# Create the interpolator object
D_interp = rgi((x_positions, y_positions, z_positions), D_values)

# Interpolate the plane at z=0
plane = D_interp(z=0)

plane变量现在将是一个2D数组,包含函数D在x-y平面z=0处的插值。
您可以对要插值的每个z值重复此过程。例如,要沿着z轴插值所有平面,可以使用如下循环:

from scipy.interpolate import RegularGridInterpolator as rgi

# Define the input values for the x, y, and z dimensions
x_positions = ...
y_positions = ...
z_positions = ...

# Define the values of the function D at each point in the grid
D_values = ...

# Create the interpolator object
D_interp = rgi((x_positions, y_positions, z_positions), D_values)

# Interpolate all the planes along the z-axis
planes = []
for z in z_positions:
  plane = D_interp(z=z)
  planes.append(plane)

planes变量现在将是一个2D数组列表,其中包含z_positions中每个z值在x-y平面上的函数D的插值。

vhipe2zx

vhipe2zx3#

您可以生成每个平面的meshgrid,将坐标解缠为一系列点,在每个点处进行插值,最后将结果重新整形为一系列平面:

x_positions = np.arange(0, 355)
y_positions = np.arange(0, 155)
z_positions = np.arange(0, 303)

z_mesh, x_mesh, y_mesh = np.meshgrid(z_positions, x_positions, y_positions, indexing='ij')
pts = np.vstack([x_mesh.ravel(), y_mesh.ravel(), z_mesh.ravel()]).transpose()
plane = np.reshape(interp(pts), x_mesh.shape)

在这个例子中,我在网格的第一个位置排列了z_positions,所以你得到了一个平面数组。

相关问题