我已经生成了一个在 matplotlib 中复制 matlab 瀑布行为的函数,但我认为它在性能方面不是最好的解决方案。
我从 matplotlib 文档中的两个示例开始:多色线和3d plot 中的多条线。从这些示例中,我只看到可以根据示例后面的 z 值绘制颜色在给定颜色图之后变化的线条,这正在重塑输入数组以通过 2 个点的线段绘制线并将线段的颜色设置为两点之间的 z 平均值。
因此,给定输入矩阵n,m
matrixes和X
,该函数在最小维度上循环以绘制示例中的每条线,如示例中的 2 个点段,其中按段绘制的重塑是使用与例子。Y
Z
n,m
def waterfall_plot(fig,ax,X,Y,Z):
'''
Make a waterfall plot
Input:
fig,ax : matplotlib figure and axes to populate
Z : n,m numpy array. Must be a 2d array even if only one line should be plotted
X,Y : n,m array
'''
# Set normalization to the same values for all plots
norm = plt.Normalize(Z.min().min(), Z.max().max())
# Check sizes to loop always over the smallest dimension
n,m = Z.shape
if n>m:
X=X.T; Y=Y.T; Z=Z.T
m,n = n,m
for j in range(n):
# reshape the X,Z into pairs
points = np.array([X[j,:], Z[j,:]]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
lc = LineCollection(segments, cmap='plasma', norm=norm)
# Set the values used for colormapping
lc.set_array((Z[j,1:]+Z[j,:-1])/2)
lc.set_linewidth(2) # set linewidth a little larger to see properly the colormap variation
line = ax.add_collection3d(lc,zs=(Y[j,1:]+Y[j,:-1])/2, zdir='y') # add line to axes
fig.colorbar(lc) # add colorbar, as the normalization is the same for all, it doesent matter which of the lc objects we use
因此,可以使用与 matplotlib 曲面图相同的输入矩阵轻松生成看起来像 matlab 瀑布的图:
import numpy as np; import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from mpl_toolkits.mplot3d import Axes3D
# Generate data
x = np.linspace(-2,2, 500)
y = np.linspace(-2,2, 40)
X,Y = np.meshgrid(x,y)
Z = np.sin(X**2+Y**2)
# Generate waterfall plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
waterfall_plot(fig,ax,X,Y,Z)
ax.set_xlabel('X') ; ax.set_xlim3d(-2,2)
ax.set_ylabel('Y') ; ax.set_ylim3d(-2,2)
ax.set_zlabel('Z') ; ax.set_zlim3d(-1,1)
该函数假设在生成网格网格时,x
数组是最长的,默认情况下,线的 y 是固定的,x 坐标是变化的。但是,如果 y 维度的大小较大,则矩阵会被转置,从而生成具有固定 x 的线。因此,生成尺寸倒置 (len(x)=40
和len(y)=500
) 的网格网格会产生: