3D Waterfall Plot with Colored Heights

2024/10/14 7:18:25

I'm trying to visualise a dataset in 3D which consists of a time series (along y) of x-z data, using Python and Matplotlib.

I'd like to create a plot like the one below (which was made in Python: http://austringer.net/wp/index.php/2011/05/20/plotting-a-dolphin-biosonar-click-train/), but where the colour varies with Z - i.e. so the intensity is shown by a colormap as well as the peak height, for clarity.

enter image description here

An example showing the colormap in Z is (apparently made using MATLAB): enter image description here

This effect can be created using the waterfall plot option in MATLAB, but I understand there is no direct equivalent of this in Python.

I have also tried using the plot_surface option in Python (below), which works ok, but I'd like to 'force' the lines running over the surface to only be in the x direction (i.e. making it look more like a stacked time series than a surface). Is this possible? enter image description here

Any help or advice greatly welcomed. Thanks.

Answer

I have generated a function that replicates the matlab waterfall behaviour in matplotlib, but I don't think it is the best solution when it comes to performance.

I started from two examples in matplotlib documentation: multicolor lines and multiple lines in 3d plot. From these examples, I only saw possible to draw lines whose color varies following a given colormap according to its z value following the example, which is reshaping the input array to draw the line by segments of 2 points and setting the color of the segment to the z mean value between the 2 points.

Thus, given the input matrixes n,m matrixes X,Y and Z, the function loops over the smallest dimension between n,m to plot each line like in the example, by 2 points segments, where the reshaping to plot by segments is done reshaping the array with the same code as the example.

def waterfall_plot(fig,ax,X,Y,Z):'''Make a waterfall plotInput:fig,ax : matplotlib figure and axes to populateZ : n,m numpy array. Must be a 2d array even if only one line should be plottedX,Y : n,m array'''# Set normalization to the same values for all plotsnorm = plt.Normalize(Z.min().min(), Z.max().max())# Check sizes to loop always over the smallest dimensionn,m = Z.shapeif n>m:X=X.T; Y=Y.T; Z=Z.Tm,n = n,mfor 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 colormappinglc.set_array((Z[j,1:]+Z[j,:-1])/2)lc.set_linewidth(2) # set linewidth a little larger to see properly the colormap variationline = ax.add_collection3d(lc,zs=(Y[j,1:]+Y[j,:-1])/2, zdir='y') # add line to axesfig.colorbar(lc) # add colorbar, as the normalization is the same for all, it doesent matter which of the lc objects we use

Therefore, plots looking like matlab waterfall can be easily generated with the same input matrixes as a matplotlib surface plot:

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

The function assumes that when generating the meshgrid, the x array is the longest, and by default the lines have fixed y, and its the x coordinate what varies. However, if the size of the y dimension is larger, the matrixes are transposed, generating the lines with fixed x. Thus, generating the meshgrid with the sizes inverted (len(x)=40 and len(y)=500) yields:

Non default waterfall plot

https://en.xdnf.cn/q/69437.html

Related Q&A

python xlsxwriter: Keep header in excel when adding a table

I have a panda dataframe that I write to a xslx file, and would like to add a table over that data. I would also like to keep the headers that I have already written, instead of adding them again. Is t…

Unexpected tokens in !DOCTYPE html in PyCharm Community Edition

I am new in using PyCharm but I am loving it gradually. I am getting a red underline on <!DOCTYPE html> and the error is "Unexpected Token".Why PyCharm shows it? I cant understand.

Indexing a numpy array with a numpy array of indexes [duplicate]

This question already has answers here:Indexing a numpy array with a list of tuples(2 answers)Index multidimensional array with index array(1 answer)Closed 5 years ago.I have a 3D numpy array data and …

Input redirection with python

I have the following program to test input redirection in Python.a = int(raw_input("Enter a number: ")) b = raw_input("Enter a string: ") print "number entered = ", a prin…

TypeError: can only concatenate str (not numpy.int64) to str

I want to print the variable based on the index number based on the following dataset:Here I used the following code:import pandas as pdairline = pd.read_csv("AIR-LINE.csv")pnr = input("…

Saving scatterplot animations with matplotlib produces blank video file

I am having a very similar problem to this questionbut the suggested solution doesnt work for me. I have set up an animated scatter plot using the matplotlib animation module. This works fine when it i…

How to group near-duplicate values in a pandas dataframe?

If there are duplicate values in a DataFrame pandas already provides functions to replace or drop duplicates. In many experimental datasets on the other hand one might have near duplicates. How can one…

python looping and creating new dataframe for each value of a column

I want to create a new dataframe for each unique value of station.I tried below which gives me only last station data updated in the dataframe = tai_new.itai[station].unique() has 500 values.for i in t…

How to put more whitespace around my plots?

I have a figure that contains two subplots in two rows and one column like so:fig, (ax1, ax2) = subplots(nrows=2,ncols=1, )The two subplots are pie charts, therefore I want their axes to be square. Aft…

using ols from statsmodels.formula.api - how to remove constant term?

Im following this first example in statsmodels tutorial:http://statsmodels.sourceforge.net/devel/How do I specify not to use constant term for linear fit in ols?# Fit regression model (using the natur…