Search code examples
pythonmatplotlibwaterfall

The plot3d figure in matplotlib is somewhat canted


I am using matplotlib to get a water fall figure, but the results look very strange. Anyone have any idea what could be wrong with it?
Here I attached the figures. The second one is the same data but in an ordinary plot. In the waterfall figure, why the color is not fully filled?

enter image description here

enter image description here

Here is the code:

def water_fall_1(x,y,Z):
    #x=[...]
    #y=[...]
    #Z=[[z1],[z2],...z[ny]]
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.collections import PolyCollection
    from matplotlib.colors import colorConverter
    from mpl_toolkits.mplot3d import Axes3D

    figs=[]
    for jc in range(len(y)):
        figs.append(list(zip(x,Z[jc])))
    x=np.array(x)
    y=np.array(y)
    Z=np.array(Z)
    xmin=np.floor(np.min((x.astype(np.float))))
    xmax=np.ceil(np.max((x.astype(np.float))))
    ymin=np.min((y.astype(np.float)))
    ymax=np.max((y.astype(np.float)))
    zmin=(np.min((Z.astype(np.float))))
    zmax=np.max((Z.astype(np.float)))

    fig=plt.figure()
    ax = Axes3D(fig)
    poly = PolyCollection(figs, facecolors=colorConverter.to_rgba("r", alpha=0.5))
    ax.add_collection3d(poly, zs=y.astype(np.float), zdir='y')
    ax.set_xlim(xmin,xmax)
    ax.set_ylim(ymin,ymax)
    ax.set_zlim(zmin,zmax)
    ax.set_xlabel('$\omega$')
    ax.set_ylabel('$T$')
    #ax.set_zlabel('$\\frac{1}{2}$')
    plt.show()

Solution

  • The curve is fully filled. I.e. the surface in between the points of the curve is red.

    Consider the following example:

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.collections import PolyCollection
    from mpl_toolkits.mplot3d import Axes3D
    
    bottom=-0.3
    x = np.linspace(0,6, num=50)
    z = np.sinc(x-4)
    verts = zip(x,z)
    
    #verts=verts + [(x.max(),bottom),(x.min(),bottom)]
    
    fig=plt.figure()
    ax = Axes3D(fig)
    poly = PolyCollection([verts], facecolors="r", alpha=0.5)
    ax.add_collection3d(poly, zs=1, zdir='y')
    ax.set_xlim(x.min(),x.max())
    ax.set_ylim(0,2)
    ax.set_zlim(bottom,z.max())
    
    plt.show()
    

    which produces the following plot, where everything between the points of the curve is filled as expected.

    enter image description here

    If we now want to have the area between the curve and some bottom line filled, we would need to add some points,

    verts=verts + [(x.max(),bottom),(x.min(),bottom)]
    

    such that the bottom line is part of the curve and can thus be filled as well. enter image description here