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:
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.
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.
To decrease colorbar width in Matplotlib, we can use shrink in colorbar() method.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With