Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib spectrogram intensity legend (colorbar)

I'm using matplotlib's specgram function to generate a spectrogram. I've attempted to include a colorbar off to the right of the spectrogram to give an indication of dB-to-color-mapping.

For some reason though, the dB indicated by the colorbar do not make sense.

Perhaps I've not generated the colorbar correctly? Perhaps there is some parameter that I need to pass to specgram?

The signal I'm generating is a 1Khz, 2Vpp sine sampled at 32Khz.

I'm expecting that the dark red peak on the spectrogram corresponds to 0dB (Meaning that +1V is my reference)

Anybody have any idea what is wrong with my approach?

def plot_specgram(data, title='', x_label='', y_label='', fig_size=None):
    fig = plt.figure()
    if fig_size != None:
        fig.set_size_inches(fig_size[0], fig_size[1])
    ax = fig.add_subplot(111)
    ax.set_title(title)
    ax.set_xlabel(x_label)
    ax.set_ylabel(y_label)
    pxx,  freq, t, cax = plt.specgram(data, Fs=32000)
    fig.colorbar(cax).set_label('Intensity [dB]')

plot_specgram(a,title='Spectrogram', x_label='time (in seconds)', y_label='frequency', fig_size=(14,8))

This is what I get as resulting spectrogram:

resulting plot

like image 636
brandon kinman Avatar asked Nov 30 '14 05:11

brandon kinman


People also ask

How do I change the Colorbar scale in Matplotlib?

Use the matpltolib. pyplot. clim() Function to Set the Range of Colorbar in Matplotlib. The clim() function can be used to control the range of the colorbar by setting the color limits of the plot, which are used for scaling.

How do you normalize a Colorbar in Python?

will map the data in Z linearly from -1 to +1, so Z=0 will give a color at the center of the colormap RdBu_r (white in this case). Matplotlib does this mapping in two steps, with a normalization from the input data to [0, 1] occurring first, and then mapping onto the indices in the colormap.

How do I make the color bar smaller in Matplotlib?

To decrease colorbar width in Matplotlib, we can use shrink in colorbar() method.


1 Answers

First of all, please supply your a vector, since it seems to have some kind of harmonics.

This is a bit trial and error, but this seems to produce the correct scaling:

NFFT = 256
ax.specgram(x/(NFFT/2), NFFT=NFFT, Fs=fs, mode='magnitude', window=plt.window_none)

Using a window seems to lose about 1/2 of the peak power, you can of course adjust for this.

A complete example where I have limited the dynamic range to 40dB (as an example, if you want to hide the small stuff).

import numpy as np
import pylab as plt

# generate a 1kHz sine wave
fs = 32e3
t = np.arange(0, 15, 1.0/fs)
f0 = 1e3
A = 1
x = A*np.sin(2*np.pi*f0*t)

fig, ax = plt.subplots()
cmap = plt.get_cmap('viridis')
vmin = 20*np.log10(np.max(x)) - 40  # hide anything below -40 dBc
cmap.set_under(color='k', alpha=None)

NFFT = 256
pxx,  freq, t, cax = ax.specgram(x/(NFFT/2), Fs=fs, mode='magnitude',
                                 NFFT=NFFT, noverlap=NFFT/2,
                                 vmin=vmin, cmap=cmap,
                                 window=plt.window_none)
fig.colorbar(cax)

print np.max(pxx) # should match A

resulting image

like image 129
oystein Avatar answered Sep 30 '22 23:09

oystein