My question is the following:
I have all the values that I need for a spectrogram (scipy.fftpack.fft
). I would like to create a 3D spectrogram in python.
In MATLAB this is a very simple task, while in python it seems much more complicated. I tried mayavi, 3D plotting matplotlib but I have not managed to do this.
Thanks
My code:
import numpy as np import pandas as pd import numpy as np from scipy import signal import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm from matplotlib.collections import PolyCollection fs = 11240. t = 10 time = np.arange(fs*t) / fs frequency = 1000. mysignal = np.sin(2.0 * np.pi * frequency * time) nperseg = 2**14 noverlap = 2**13 f, t, Sxx = signal.spectrogram(mysignal, fs, nperseg=nperseg,noverlap=noverlap) myfilter = (f>800) & (f<1200) fig,ax = plt.subplots() plt.pcolormesh(t, f[myfilter], 10*np.log10(Sxx[myfilter, :]), cmap='jet') plt.show() fig = plt.figure() ax = fig.gca(projection='3d') x = [] y = [] for counter,i in enumerate(f): x.append(np.array([i for k in t])) y.append(t) ax.plot_surface(np.array(x), np.array(y), 10.0*np.log10(Sxx), cmap=cm.coolwarm) plt.show()
Similar unanswered question: How to convert a spectrogram to 3d plot. Python
Desired plot in python like Matlab’s figure (last plot here: https://www.mathworks.com/help/signal/ref/spectrogram.html)
Advertisement
Answer
You just need to get your arrays in the right shape:
fs = 11240. t = 10 time = np.arange(fs*t) / fs frequency = 1000. mysignal = np.sin(2.0 * np.pi * frequency * time) nperseg = 2**14 noverlap = 2**13 f, t, Sxx = signal.spectrogram(mysignal, fs, nperseg=nperseg,noverlap=noverlap) myfilter = (f>800) & (f<1200) f = f[myfilter] Sxx = Sxx[myfilter, ...] fig = plt.figure() ax = fig.gca(projection='3d') ax.plot_surface(f[:, None], t[None, :], 10.0*np.log10(Sxx), cmap=cm.coolwarm) plt.show()