How to plot Spectrogram using STFT in python?

17,284

Solution 1

what you can do is use this

first method:

import scipy.io.wavfile as wav
import scipy.signal as signal
from matplotlib import pyplot as plt

sample_rate, samples = wav.read(filename)
f, t, Zxx = signal.stft(samples, fs=sample_rate)
plt.pcolormesh(t, f, np.abs(Zxx), cmap=cmap)

or the second method:

plt.specgram(samples, cmap=cmap, Fs=sample_rate)

I found the second one have a better visualization effect. Not sure how to make the first one look as good as the second one though.

Solution 2

import os
import librosa
import librosa.display
import IPython.display as ipd
import numpy as np
import matplotlib.pyplot as plt

filename = '<yourfile name/ location>'
x, sr = librosa.load(filename)

import librosa.display                   #explicitly import librosa.display
X = librosa.stft(x)                      #perform short-term fourier transfrom               
Xdb = librosa.amplitude_to_db(abs(X))    #convert an amplitude spectrogram to dB-scaled spectrogram.
plt.figure(figsize=(15, 5))              #initialize the fig size
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz')
plt.colorbar()```
Share:
17,284
Jay Krishna
Author by

Jay Krishna

Updated on June 04, 2022

Comments

  • Jay Krishna
    Jay Krishna about 2 years

    I calculated STFT of uint8 I/Q data and stored it in a numpy matrix where each row stores STFT of one window as shown in sudo code below.

    #k= length of window
    #fs= Sampling frequency
    #n= Number of STFT calculated
    #matrix= Initially empty numpy array
    
    for i in range(0,n):
      t=data[start:end,:]   #start & end calculated with each iteration
      t=t.flatten()
      t=t-127.5
      array = np.empty(t.shape[0]//2, dtype=np.complex128)
      array.real = t[::2]
      array.imag = t[1::2]
    
      transform=(np.fft.fft(temp_array))
      line = 2*abs(transform)/k
    
      #Inserting row into numpy array
      if(i==0):
         matrix = np.hstack((matrix, line))
      else:
         matrix = np.vstack((matrix, line))
    

    Now how can I plot frequency vs time Spectrogram ?

    • user2027202827
      user2027202827 about 7 years
      have you looked into matplotlib?
    • Jay Krishna
      Jay Krishna about 7 years
      Yes I did both into matplotlib as well as scipy but both were not working fine with complex numpy array
    • MB-F
      MB-F about 7 years
      Why complex arrays? Taking the absolute value of the FFT should result in real values that can be easily plotted with matplotlib's imshow. Just take care not to initialize matrix with complex data type.
    • Jay Krishna
      Jay Krishna about 7 years
      @kazemakase You mean using imshow with extent after taking absolute i.e ax.imshow(np.absolute(matrix),extent=[0,100,0,1]) ? I am assuming frequency will be on Y-axis.
    • MB-F
      MB-F about 7 years
      @JayKrishna yes, that should work as expected. Stil... it looks like you only put absolute values into line and thus in matrix anyway so it is surprising that you have complex values in matrix.
    • Ahmed Fasih
      Ahmed Fasih about 7 years
      See the example at the bottom of docs.scipy.org/doc/scipy/reference/generated/…
    • Tom Wyllie
      Tom Wyllie almost 5 years
  • Chase Roberts
    Chase Roberts almost 5 years
    cmap is undefined.
  • jcoppens
    jcoppens over 4 years
    (second) cmap must be eplaced with the name of a colormap. In the Gallery on matplotlib.org is a drawing with all available colormaps, their names. and how to use them.
  • jcoppens
    jcoppens over 4 years
    Oops. Gallery is not on the front page anymore. It's under examples now. Check this: matplotlib.org/gallery/color/…
  • alienflow
    alienflow over 3 years
    To achieve on the first the looks of second just do np.log() of np.abs(Zxx)