5

我正在尝试使用以下代码使用 matplotlib 绘制曲面:

from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p

vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))

surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, alpha=1,cmap=cm.jet,  linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

如果你运行它,你会看到一个蓝色的表面,但我想使用 jet 的整个颜色范围......我知道有一个类“matplotlib.colors.Normalize”,但我不知道如何使用它。您能否添加必要的代码才能做到这一点?

4

3 回答 3

18

我意识到海报的问题已经解决了,但颜色标准化的问题从未得到解决。因为我已经弄清楚我是怎么想的,我会把它放在这里给其他可能需要它的人。

首先,您创建一个规范并将其传递给绘图函数,我尝试将其添加到 OP 的代码中。

from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p
import matplotlib

vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))
Z = np.nan_to_num(Z)

# Make the norm
norm = matplotlib.colors.Normalize(vmin = np.min(Z), vmax = np.max(Z), clip = False)

# Plot with the norm
surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, norm=norm, alpha=1,cmap=cm.jet,     linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

对于“imshow”命令,规范的工作方式相同。

于 2012-09-18T15:15:33.453 回答
5

正如 JoshAdel 在评论中指出的那样(信用属于他),当 aNaN在 Z 数组中时,表面图似乎不正确地排列颜色图。一个简单的解决方法是简单地将 NaN 转换为零或非常大或非常小的数字,以便可以将颜色图标准化为 z 轴范围。

from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p

vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))
Z = np.nan_to_num(Z) # added this line

surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, alpha=1,cmap=cm.jet,  linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()
于 2011-03-07T02:32:53.413 回答
4

回答一个老问题,我知道,但发布的答案至少在我的情况下有点不令人满意。对于那些仍然在这里磕磕绊绊的人,我给出了一个对我有用的解决方案。

首先,我不想用零来代替 NaN,因为对我来说,它们代表缺少或未定义数据的点。我宁愿没有在这些点上绘制任何东西。其次,我的数据的整个z范围都远高于零,所以用零点图会导致一个丑陋且比例不良的图。

leifdenby 给出的解决方案非常接近,因此 +1 (尽管正如所指出的,显式标准化不会添加到早期的解决方案中)。我刚刚放弃了从 NaN 到零的替换,并在色标归一化中使用了函数nanminandnanmax而不是minand 。max这些函数给出了数组的最小值和最大值,但只是忽略了所有的 NaN。现在代码如下:

# Added colors to the matplotlib import list
from matplotlib import cm, colors
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p


vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))

# MAIN IDEA: Added normalisation using nanmin and nanmax functions
norm = colors.Normalize(vmin = np.nanmin(Z), 
                        vmax = np.nanmax(Z))

# Added the norm=norm parameter
surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, alpha=1, norm=norm, cmap=cm.jet,  linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

运行这个,我得到一个正确缩放的图,缺少 (0, 0) 数据点。这也是我认为最可取的行为,因为所讨论的函数似乎不存在从 (x, y) 到 (0, 0) 的限制。

这是我对 StackOverflow 的第一个贡献,我希望这是一个好的贡献(眨眼)。

于 2015-12-30T19:26:54.007 回答