(python)绘制 3d 表面,颜色图作为第 4 维,x、y、z 的函数

新手上路,请多包涵

我正在尝试绘制一个 3d 表面,其中三个维度中的每一个都在一个单独的值数组中,并且表面在每个坐标处的着色是 x、y、z 的函数。一种 numpy.pcolormesh 但在 4D 中,而不是 3D。 3D 图由下式给出:

 from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.logspace(-1.,np.log10(5),50)
y = np.linspace(6,9,50)
z = np.linspace(-1,1,50)
colors = LikeBeta(y,range(50),range(50))
ax.plot_trisurf(x,y,z,cmap=colors,linewidth=0.2)

在哪里

def LikeBeta(rho0,r0,beta):
    M0 = 10**rho0*r0_array[r0]**3
    I = cst*M0*sigma_los_beta[beta,:,r0]
    S = dv**2+I
    res = (np.log(S) + (v-u)**2/S).sum()
    return res/2.

可能 cmap=colors 是错误的,但问题出在别处。我收到以下错误:

 ----> 8 colors = LikeBeta(y,range(50),range(50))
----> 4     I = cst*M0*sigma_los_beta[beta,:,r0]
    ValueError: operands could not be broadcast together with shapes (50,) (50,353)

确实 sigma_los_beta 是我单独评估的数组,其形状 (50,353,50) 那些 353 是我必须拥有的数据。

如何将此函数转换为与 plot_trisurf 的其他条目兼容的形式?

抱歉,但我无法提供最低限度的工作代码,因为 dv、v 和 u 是数据。非常感谢您的帮助。干杯

原文由 andrea 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.7k
2 个回答

这个 答案解决了 4d 曲面图问题。它使用 matplotlib 的 plot_surface 函数而不是 plot_trisurf

基本上,您想将 x、y 和 z 变量重塑为相同维度的二维数组。要将第四维添加为颜色图,您必须提供另一个与轴变量具有相同维数的二维数组。

下面是 3d 图的示例代码,其中颜色图对应于 x 值。 facecolors 参数用于根据您的喜好更改颜色图。请注意,它的值是从 matplotlib.cm.ScalarMappable 类中的 to_rgba() 函数中获取的。

 import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# domains
x = np.logspace(-1.,np.log10(5),50) # [0.1, 5]
y = np.linspace(6,9,50)             # [6, 9]
z = np.linspace(-1,1,50)            # [-1, 1]

# convert to 2d matrices
Z = np.outer(z.T, z)        # 50x50
X, Y = np.meshgrid(x, y)    # 50x50

# fourth dimention - colormap
# create colormap according to x-value (can use any 50x50 array)
color_dimension = X # change to desired fourth dimension
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
m = plt.cm.ScalarMappable(norm=norm, cmap='jet')
m.set_array([])
fcolors = m.to_rgba(color_dimension)

# plot
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
fig.canvas.show()

我引用的答案(和其他人)提到你应该标准化你的第四维数据。似乎可以通过像我在代码示例中那样显式设置颜色图的限制来避免这种情况。

原文由 Frik 发布,翻译遵循 CC BY-SA 3.0 许可协议

非常感谢@Frik 的出色 回答,它帮助我按照 OP 的要求实现了类似的情节。

但是,我发现可以对代码进行一些简化并且可能会引起人们的兴趣。片段和下图。

 import matplotlib.pyplot as plt
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D  # noqa: F401 unused import
from mpl_toolkits.mplot3d.axes3d import get_test_data
import numpy as np
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
X, Y, Z = get_test_data(0.05)
C = np.linspace(-5, 5, Z.size).reshape(Z.shape)
scamap = plt.cm.ScalarMappable(cmap='inferno')
fcolors = scamap.to_rgba(C)
ax.plot_surface(X, Y, Z, facecolors=fcolors, cmap='inferno')
fig.colorbar(scamap)
plt.show()

在此处输入图像描述

最后,我还想评论@Frik 写的内容:

我引用的答案(和其他人)提到你应该标准化你的第四维数据。似乎可以通过像我在代码示例中那样显式设置颜色图的限制来避免这种情况。

我发现这个说法是不正确的。事实上,如果看一看 to_rgba ,可以看到有一个 norm 关键字,默认设置为 True 这正是规范化发生的地方。还包括以下声明:

如果 norm 为 False,则不对输入数据执行归一化,并假定其在 (0-1) 范围内。

您确实希望您的数据位于 (0-1)。

原文由 Patol75 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题