Search code examples
pythonspectral-density

Rotate PSD plot in Python by 90 degrees


I have generated a Power Spectral Density (PSD) plot using the command

plt.psd(x,512,fs)

I am attempting to duplicate this plot from a paper:

enter image description here

I am able to get the spectrogram and the PSD graph. I however need to get the PSD rotated 90 degrees counter clockwise to show up properly. Can you assist me in rotating the PSD graph 90 degrees counterclockwise? Thanks!

Here is the code that I have so far:

import matplotlib.pyplot as plt
from matplotlib import transforms
import numpy as np
from numpy.fft import fft, rfft
from scipy.io import wavfile
from scipy import signal
import librosa
import librosa.display

from matplotlib.gridspec import GridSpec

input_file = (r'G:/File.wav')

fs, x = wavfile.read(input_file)
nperseg = 1025
noverlap = nperseg - 1
f, t, Sxx = signal.spectrogram(x, fs,
                               nperseg=nperseg,
                               noverlap=noverlap,
                               window='hann')

def format_axes(fig):
    for i, ax in enumerate(fig.axes):
        ax.tick_params(labelbottom=False, labelleft=False)

fig = plt.figure(constrained_layout=True)

gs = GridSpec(6, 5, figure=fig)
ax1 = plt.subplot(gs.new_subplotspec((0, 1), colspan=4))

ax2 = plt.subplot(gs.new_subplotspec((1, 0), rowspan=4))

plt.psd(x, 512, fs)  # How to rotate this plot 90 counterclockwise?
plt.ylabel("")
plt.xlabel("")
# plt.xlim(0, t)

fig.suptitle("Sound Analysis")
format_axes(fig)

plt.show()

Solution

  • I would suggest outputting the values for the power spectrum and the frequencies in order to manually create the rotated plot.

    For instance, let us consider a random array x consisting of 10,000 samples, sampled at Fs=1,000:

    import matplotlib.pyplot as plt
    import numpy as np
    x=np.random.random(10000)
    fs=1000
    Pxx, freq = plt.psd(x, 512, fs)
    

    This snippet retuns the following image:

    enter image description here

    In order to create the rotated plot, just use plot:

    plt.plot(10*np.log10(Pxx),freq)
    plt.xlabel("Power Spectrial Density (dB/Hz)")
    plt.ylabel('Frequency')
    

    This will return:

    enter image description here

    EDIT: please keep in mind that the function psd outputs Pxx, but what you need to plot is 10*np.log10(Pxx). As stated on the psd help page: for plotting, the power is plotted as 10log10(Pxx) for decibels, though Pxx itself is returned.