我正在尝试使用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()
如果你运行它你会看到一个蓝色的表面,但我想使用整个颜色范围的喷射...我知道有一个类“matplotlib.colors.Normalize”,但我不知道如何用它。你可以加上必要的代码吗?
答案 0 :(得分: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”命令的工作方式相同。
答案 1 :(得分:4)
正如JoshAdel在评论中指出的那样(信用属于他),当NaN
在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()
答案 2 :(得分:3)
回答一个老问题,我知道,但发布的答案至少在我的情况下有些不尽如人意。对于那些仍然在这里磕磕绊绊的人,我给出了一个对我有用的解决方案。
首先,我不想使用零来替换NaN,因为对我而言,它们代表缺少或未定义数据的点。我宁愿不在这些点上绘制任何。其次,我的数据的整个 z 范围都高于零,所以用零点打印图将导致一个丑陋且难以缩放的图。
leifdenby给出的解决方案非常接近,因此+1(尽管如此指出,显式规范化不会添加到早期的解决方案中)。我刚刚删除了NaN-to-zero替换,并在色标规范化中使用了函数nanmin
和nanmax
而不是min
和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的第一次贡献,我希望它是一个很好的(wink)。