2014-11-30 13 views
5

Uso la funzione specgram di matplotlib per generare uno spettrogramma. Ho tentato di includere una barra colori a destra dello spettrogramma per fornire un'indicazione della mappatura da dB a colore.Legenda intensità spettrogramma Matlotlib (colorbar)

Per qualche motivo, tuttavia, il dB indicato dalla barra dei colori non ha senso.

Forse non ho generato correttamente la barra di colore? Forse c'è qualche parametro che ho bisogno di passare a specgram?

Il segnale che sto generando è un seno 1Khz, 2Vpp campionato a 32Khz.

mi aspetto che il picco rosso scuro su spettrogramma corrisponde a 0 dB (Il che significa che + 1V è il mio riferimento)

Qualcuno ha idea di cosa è sbagliato con il mio approccio?

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)) 

Questo è ciò che ottengo come risultante spettrogramma:

resulting plot

+0

Dalla mappa dei colori, il rosso scuro * fa * sembrano corrispondere a 0. Solo che 0 non è visualizzato ... Il 0db (rosso scuro) corrisponde alla componente spettrale di picco di 1kHz ... Il blu, come previsto, ha un valore di intensità inferiore (<< 0) poiché sono solo artefatti sviluppati a causa del campionamento ... sinceramente non vedo nulla di sbagliato con il tuo codice/grafico ... –

+0

In realtà, probabilmente, ciò che vedi è il risultato di una funzione della finestra che non stai prendendo in considerazione. Sono abbastanza sicuro che 'specgram' utilizza una finestra di Hanning come predefinita, che potrebbe compromettere ciò che ci si aspetta dal ridimensionamento. – Ajean

risposta

3

Prima di tutto, si prega di fornire il vostro a vettore, dal momento che sembra avere un qualche tipo di armoniche.

Questa è una prova ed errore po ', ma questo sembra produrre la corretta scalatura:

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

Utilizzando una finestra sembra perdere circa 1/2 della potenza di picco, si può ovviamente registrare per ottenere questo .

Un esempio completo in cui ho limitato l'intervallo dinamico a 40 dB (ad esempio, se si desidera nascondere le piccole cose).

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