# How to calculate the PSD from the complex calculated STFT?

I have calculated the STFT with scipy python library:

f_spec, t_spec, Spectro= sc.signal.spectrogram(My_Signal, fs=1.0, window='hamming', nperseg=180,
noverlap=None, nfft=2048, detrend=False, return_onesided=False, scaling='density',
axis=-1, mode='complex')


I wanted to get the same result as spectrogram function of MATLAB and now I want to calcluate its PSD in dB. In fact I have found several expression in internet such as :

PSD=Spectro^2


or :

PSD = 10*log10(abs(Spectro))


I am not sure what to use can any one help me?

In general, if you have complex spectrum and need PSD in dB the mathematical equation is

$$P_{xx} = 20\cdot\log_{10}|X_{x}|,$$ where $$P_{xx}$$ is your PSD in dB and $$X_{x}$$ is your complex STFT spectrum (variable Spectro in your case).

In SciPy documentation for scipy.signal.spectrogram is mentioned, that you can compute spectrogram with different modes (‘psd’, ‘complex’, ‘magnitude’, ‘angle’, ‘phase’). You have chosen mode='complex', which returns complex STFT, so you should get PSD from equation above. If you have chosen mode='psd' you would get PSD e.g. $$S_{xx}$$ (Spectro in your case) in the first place and to convert it to dB your equation is $$P_{xx} = 10\cdot\log_{10}S_{xx}.$$

However, if you want to plot same spectrogram as the MATLAB one I would choose equivalent matplotlib.pyplot.specgram, which is very similar and you can plot PSD already in dB with this tool.

I normally use the Welch method to calculate and plot the PSD of a signal.

signal_f, signal_psd = sp.welch(signal, sampling_frequency, return_onesided=False, nperseg=256)
signal_f = np.fft.fftshift(signal_f)
signal_psd = np.fft.fftshift(signal_psd)

plt.semilogy(signal_f, signal_psd, label = 'PSD')


Maybe it helps you!

• can I use the welch method without overlapping because I aim to calculate the PSD in dB without overlapping Jan 16 '19 at 6:15
• Yes, although I always used it on default settings. I just tried with noverlap = 0. Refer here, docs.scipy.org/doc/scipy-0.14.0/reference/generated/…. The results are slightly different but not much. Jan 16 '19 at 10:51