python - 如何将 3D 表面颜色图映射到标量函数?

标签 python matplotlib plot 3d

我有一个标量函数来表示球面的电势。我想针对给定的半径绘制曲面,并根据势函数将其点链接到颜色图。

如何将该标量函数映射到表面中的颜色图?我怀疑它一定是在传递给函数 ax.plot_surface 的参数中。我尝试使用参数:facecolors=potencial(x,y,z),但它给了我一个ValueError: Invalid RGBA argument。看着source code of the third example ,有:

# Create an empty array of strings with the same shape as the meshgrid, and
# populate it with two colors in a checkerboard pattern.
colortuple = ('y', 'b')
colors = np.empty(X.shape, dtype=str)
for y in range(ylen):
    for x in range(xlen):
        colors[x, y] = colortuple[(x + y) % len(colortuple)]

我不明白,也不知道如何链接到标量函数。

我的代码

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

def potencial(x,y,z, a=1., v=1.):
    r = np.sqrt( np.square(x) + np.square(y) + np.square(z) )    
    p = z/r #cos(theta)
    asr = a/r
    s=0
    s += np.polyval(special.legendre(1), p) * 3/2*np.power(asr, 2)
    s += np.polyval(special.legendre(3), p) * -7/8*np.power(asr, 4)
    s += np.polyval(special.legendre(5), p) * 11/16*np.power(asr, 6)    
    return v*s

# Make data
def sphere_surface(r):
    u = np.linspace(0, 2 * np.pi, 100)
    v = np.linspace(0, np.pi, 100)
    x = r * np.outer(np.cos(u), np.sin(v))
    y = r * np.outer(np.sin(u), np.sin(v))
    z = r * np.outer(np.ones(np.size(u)), np.cos(v))
    return x,y,z

x,y,z = sphere_surface(1.5)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Plot the surface
surf = ax.plot_surface(x,y,z, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=5)
# This is mapping the color to the z-axis value

ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
plt.show()

最佳答案

原则上,有两种方法可以在 matplotlib 中为曲面图着色。

  1. 使用 cmap 参数指定颜色图。在这种情况下,将根据 z 数组选择颜色。如果不需要,
  2. 使用facecolors 参数。这需要一个与 z 形状相同的颜色数组。

所以在这种情况下我们需要选择选项 2 并构建一个颜色数组。 为此,人们可以选择一种颜色图。颜色图将 0 到 1 之间的值映射到颜色。由于势能的值远高于和低于该范围,因此需要将它们归一化到 [0,1] 范围内。
Matplotlib 已经提供了一些辅助函数来执行此归一化,并且由于势具有 1/x 依赖性,因此对数色标可能是合适的。

最后,面部颜色可能会被赋予一个数组

colors = cmap(norm(potential(...)))

现在缺少的部分是颜色条。为了将颜色条链接到曲面图中的颜色,我们需要使用颜色图和标准化实例手动设置一个 ScalarMappable,然后将其提供给颜色条。

sm = plt.cm.ScalarMappable(cmap=plt.cm.coolwarm, norm=norm)
sm.set_array(pot)
fig.colorbar(sm, shrink=0.5, aspect=5)

这是完整的示例。

from __future__ import division
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
from scipy import special    

def potencial(x,y,z, a=1., v=1.):
    r = np.sqrt( np.square(x) + np.square(y) + np.square(z) )    
    p = r/z #cos(theta)
    asr = a/r
    s=0
    s += np.polyval(special.legendre(1), p) * 3/2*np.power(asr, 2)
    s += np.polyval(special.legendre(3), p) * -7/8*np.power(asr, 4)
    s += np.polyval(special.legendre(5), p) * 11/16*np.power(asr, 6)    
    return v*s

# Make data
def sphere_surface(r):
    u = np.linspace(0, 2 * np.pi, 100)
    v = np.linspace(0, np.pi, 100)
    x = r * np.outer(np.cos(u), np.sin(v))
    y = r * np.outer(np.sin(u), np.sin(v))
    z = r * np.outer(np.ones(np.size(u)), np.cos(v))
    return x,y,z

x,y,z = sphere_surface(1.5)
pot = potencial(x,y,z)


norm=matplotlib.colors.SymLogNorm(1,vmin=pot.min(),vmax=pot.max())
colors=plt.cm.coolwarm(norm(pot))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Plot the surface
surf = ax.plot_surface(x,y,z, facecolors=colors,
                       linewidth=0, antialiased=False)
# Set up colorbar
sm = plt.cm.ScalarMappable(cmap=plt.cm.coolwarm, norm=norm)
sm.set_array(pot)
fig.colorbar(sm, shrink=0.5, aspect=5)


ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
plt.show()

enter image description here

关于python - 如何将 3D 表面颜色图映射到标量函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43720848/

相关文章:

python - Windows 上使用 Cygwin OpenSSH 的 Paramiko 找不到known_hosts 文件

python - 如何在 Databricks 中检索实验中的 model.pkl

python - 在文件中搜索单词并打印该单词在 python 中出现的行号

python - 在 matplotlib 图上裁剪文本

python - 从 Arduino 到 Python 数组的字符串列表

python - 在 Matplotlib/Python 中更改极坐标图的轴选项

python - 改变 pyplot 中 x 轴标签的增量

python - 从纬度/经度坐标计算像素值(使用 matplotlib basemap )

r - 将杜威和卢路径分析结果绘制为 R 中的路径图

r 绘制文本添加变量以使文本加粗