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.
MATLAB:
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')
Python:
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(2np.pi10000t) + np.sin(2np.pi20000t)
nsc = math.floor(50e-3fs);
nov = math.floor(nsc0.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()

Sxx_psd_dBis already in theimagescline... maybe I edited it as you were writing your comment though. No, the bottom block isn't what you had. Notice the extra output argumentPxx. That's the PSD-scaled spectrogram. Please look at the documentation. With either these blocks, I get the same exact scaling as the Python version, why are you saying the "scale is still incorrect"? – Jdip Mar 16 '23 at 18:44mode='psd'. I've edited my answer, should be good now! – Jdip Mar 17 '23 at 17:27