Matplotlib 3D瀑布情节与彩色高度

时间:2017-09-22 13:53:33

标签: python matplotlib 3d surface matplotlib.mlab

我试图在3D中可视化数据集,其中包含使用Python和Matplotlib的x-z数据的时间序列(沿y)。

我想创建一个如下图所示的图(使用Python制作:http://austringer.net/wp/index.php/2011/05/20/plotting-a-dolphin-biosonar-click-train/),但颜色随Z变化 - 即强度也由色图显示作为峰高,为了清晰起见。

enter image description here

显示Z中色彩映射的示例(显然是使用MATLAB制作的): enter image description here

可以使用MATLAB中的瀑布绘图选项创建此效果,但我知道在Python中没有直接的等效。

我也尝试过在Python(下面)中使用plot_surface选项,这项工作没问题,但是我想强迫其使用#c;在表面上行进的线仅在x方向上(即使其看起来更像是堆叠的时间序列而不是表面)。这可能吗? enter image description here

非常欢迎任何帮助或建议。感谢。

1 个答案:

答案 0 :(得分:3)

我已经生成了一个在matplotlib中复制matlab瀑布行为的函数,但我不认为它是性能方面的最佳解决方案。

我从matplotlib文档中的两个示例开始:multicolor linesmultiple lines in 3d plot。从这些例子中,我只看到可以根据示例后面的z值绘制颜色随给定颜色图而变化的线,这是重新整形输入数组以通过2个点的线段绘制线并将线段的颜色设置为两点之间的z均值。

因此,给定输入矩阵n,m矩阵XYZ,函数循环遍历n,m之间的最小维度以绘制每一行就像在示例中一样,通过2个点段,其中通过段重新绘制的重新整形使用与示例相同的代码重新整形数组。

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)

Waterfall plot

该函数假定在生成meshgrid时,x数组是最长的,默认情况下,行具有固定的y,其x坐标变化。但是,如果y维的大小较大,则矩阵被转置,生成具有固定x的线。因此,生成反转大小(len(x)=40len(y)=500)的网格网格会产生:

Non default waterfall plot