web-dev-qa-db-ja.com

色付きの高さのMatplotlib3Dウォーターフォールプロット

PythonとMatplotlibを使用して、x-zデータの時系列(yに沿った)で構成されるデータセットを3Dで視覚化しようとしています。

以下のようなプロットを作成したいと思います(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オプションを使用してみましたが、これは問題なく機能しますが、サーフェス上を走る線をx方向にのみ「強制」したいと思います(つまり、サーフェスというよりもスタックされた時系列のように見えるようにします)。これは可能ですか? enter image description here

どんな助けやアドバイスも大歓迎です。ありがとう。

7
IanRoberts

Matplotlibでmatlabウォーターフォールの動作を複製する関数を生成しましたが、パフォーマンスに関してはそれが最善の解決策ではないと思います。

Matplotlibドキュメントの2つの例から始めました: 多色線 および Dプロットの複数線 。これらの例から、2ポイントのセグメントで線を描画するように入力配列を再形成し、セグメントの色をに設定する例に従って、特定のカラーマップに従って色が変化する線を描画することしかできませんでした。 2点間のz平均値。

したがって、入力行列_n,m_行列XYおよびZが与えられると、関数は_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
_

したがって、matlabウォーターフォールのように見えるプロットは、matplotlibサーフェスプロットと同じ入力行列を使用して簡単に生成できます。

_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

この関数は、メッシュグリッドを生成するときに、x配列が最も長く、デフォルトでは線が固定されたyを持ち、そのx座標が変化することを前提としています。ただし、y次元のサイズが大きい場合、行列は転置され、xが固定された線が生成されます。したがって、サイズを反転させてメッシュグリッドを生成すると(len(x)=40およびlen(y)=500)、次のようになります。

Non default waterfall plot

4
OriolAbril