I am trying to replicate a spectrogram from MATLAB in Python. I've read other posts but they either don't use complex data or the data doesn't match between languages.
I've defined my FFT length (
nff), sample rate (
fs), overlap (
nov) and window (hamming) to all be the same between MATLAB and Python.
Here is the spectrogram from scipy and you can see the issue is the scaling is incorrect. I see that Matlab handles windowing differently than scipy. In scipy your window length and segment value (
nperseg) must be the same. This is not the case in Matlab. Also, in Matlab your FFT length does not have to be larger than your window length however that is a requirement in scipy.
I've tried to keep the parameters the same between Matlab and Python but I still am getting the wrong matrix values for plotting. I've been banging my head against the wall on this for longer than I'd like to admit, any help would be great.
fs = 50000; t = (0:1/fs:10); x = sin(2*pi*10000*t)+sin(2*pi*20000*t); nsc = floor(50e-3*fs); % Section Length nov = floor(nsc*0.90); % Percent Overlap nff = 2^12; % FFT Length %Plot Spectrogram [Sxx, spec_f,t] = spectrogram(x,hamming(nsc),nov,nff,fs); Sxx_dB = 10*log10(abs(Sxx)); figure; imagesc(t,spec_f,Sxx_dB) ylabel('Frequency (kHz)','Fontsize',12,'Interpreter','latex') xlabel('Time (sec)','Fontsize',12,'Interpreter','latex') colorbar colormap('jet') set(gca,'Fontsize',12); set(gca, 'YDir','normal')
import numpy as np from scipy import signal import math from matplotlib import pyplot as plt fs = 50000 t = np.arange(0, 10, 1/fs) x = np.sin(2*np.pi*10000*t) + np.sin(2*np.pi*20000*t) nsc = math.floor(50e-3*fs); nov = math.floor(nsc*0.90); nff = 2**12; f,t,Sxx = signal.spectrogram(x, fs=fs, window=np.hamming(nsc), noverlap=nov, nperseg=nsc, nfft=nff, mode='complex') fig1 = plt.figure() im1= plt.pcolormesh(t,f,10*np.log10(np.abs(Sxx)), cmap='jet') fig1.colorbar(im1).set_label('Intensity (dB)') plt.xlabel('Time [sec]') plt.ylabel('Frequency [Hz]') plt.show()