def CORRELOGRAMPSD(X, Y=None, lag=-1, window='hamming', norm='unbiased', NFFT=4096, window_params={}, correlation_method='xcorr'): """PSD estimate using correlogram method. :param array X: complex or real data samples X(1) to X(N) :param array Y: complex data samples Y(1) to Y(N). If provided, computes the cross PSD, otherwise the PSD is returned :param int lag: highest lag index to compute. Must be less than N :param str window_name: see :mod:`window` for list of valid names :param str norm: one of the valid normalisation of :func:`xcorr` (biased, unbiased, coeff, None) :param int NFFT: total length of the final data sets (padded with zero if needed; default is 4096) :param str correlation_method: either `xcorr` or `CORRELATION`. CORRELATION should be removed in the future. :return: * Array of real (cross) power spectral density estimate values. This is a two sided array with negative values following the positive ones whatever is the input data (real or complex). .. rubric:: Description: The exact power spectral density is the Fourier transform of the autocorrelation sequence: .. math:: P_{xx}(f) = T \sum_{m=-\infty}^{\infty} r_{xx}[m] exp^{-j2\pi fmT} The correlogram method of PSD estimation substitutes a finite sequence of autocorrelation estimates :math:`\hat{r}_{xx}` in place of :math:`r_{xx}`. This estimation can be computed with :func:`xcorr` or :func:`CORRELATION` by chosing a proprer lag `L`. The estimated PSD is then .. math:: \hat{P}_{xx}(f) = T \sum_{m=-L}^{L} \hat{r}_{xx}[m] exp^{-j2\pi fmT} The lag index must be less than the number of data samples `N`. Ideally, it should be around `L/10` [Marple]_ so as to avoid greater statistical variance associated with higher lags. To reduce the leakage of the implicit rectangular window and therefore to reduce the bias in the estimate, a tapering window is normally used and lead to the so-called Blackman and Tukey correlogram: .. math:: \hat{P}_{BT}(f) = T \sum_{m=-L}^{L} w[m] \hat{r}_{xx}[m] exp^{-j2\pi fmT} The correlogram for the cross power spectral estimate is .. math:: \hat{P}_{xx}(f) = T \sum_{m=-L}^{L} \hat{r}_{xx}[m] exp^{-j2\pi fmT} which is computed if :attr:`Y` is not provide. In such case, :math:`r_{yx} = r_{xy}` so we compute the correlation only once. .. plot:: :width: 80% :include-source: from spectrum import CORRELOGRAMPSD, marple_data from spectrum.tools import cshift from pylab import log10, axis, grid, plot,linspace psd = CORRELOGRAMPSD(marple_data, marple_data, lag=15) f = linspace(-0.5, 0.5, len(psd)) psd = cshift(psd, len(psd)/2) plot(f, 10*log10(psd/max(psd))) axis([-0.5,0.5,-50,0]) grid(True) .. seealso:: :func:`create_window`, :func:`CORRELATION`, :func:`xcorr`, :class:`pcorrelogram`. """ N = len(X) assert lag<N, 'lag must be < size of input data' assert correlation_method in ['CORRELATION', 'xcorr'] if Y is None: Y = numpy.array(X) crosscorrelation = False else: crosscorrelation = True if NFFT is None: NFFT = N psd = numpy.zeros(NFFT, dtype=complex) # Window should be centered around zero. Moreover, we want only the # positive values. So, we need to use 2*lag + 1 window and keep values on # the right side. w = Window(2.*lag+1, window, **window_params) w = w.data[lag+1:] # compute the cross correlation if correlation_method == 'CORRELATION': rxy = CORRELATION (X, Y, maxlags=lag, norm=norm) elif correlation_method == 'xcorr': rxy, _l = xcorr (X, Y, maxlags=lag, norm=norm) rxy = rxy[lag:] # keep track of the first elt. psd[0] = rxy[0] # create the first part of the PSD psd[1:lag+1] = rxy[1:] * w # create the second part. # First, we need to compute the auto or cross correlation ryx if crosscorrelation is True: # compute the cross correlation if correlation_method == 'CORRELATION': ryx = CORRELATION(Y, X, maxlags=lag, norm=norm) elif correlation_method == 'xcorr': ryx, _l = xcorr(Y, X, maxlags=lag, norm=norm) ryx = ryx[lag:] #print len(ryx), len(psd[-1:NPSD-lag-1:-1]) psd[-1:NFFT-lag-1:-1] = ryx[1:].conjugate() * w else: #autocorrelation no additional correlation call required psd[-1:NFFT-lag-1:-1] = rxy[1:].conjugate() * w psd = numpy.real(fft(psd)) return psd
@author: fellipe """ from spectrum.window import Window from matplotlib import pyplot as plt import numpy as np N = 256 #número de amostras N1 = 1024 #número de pontos da fft fs = 128 #frequência de amostragem (Hz) f1 = 30 #frequência do sinal (Hz) n = np.arange(0, N) #index n x = np.cos(2.0 * f1 * np.pi * n / fs) #gerando o sina f = np.arange(0, N1) * fs / N1 #definição do eixo da frequência h = Window(N, name='hamming') #janela hamming r = np.ones(N) #janela retangular XR = np.fft.fft(x, N1) #fft XR = np.abs(XR) / N1 #normalização XH = x * h.data #janelamento XH = np.fft.fft(XH, N1) #fft XH = np.abs(XH) / N1 #normalização plt.figure(1, [8, 5]) #Sinal sem janela (retangular) plt.subplot(211) plt.plot(f[:N1 // 2], 20.0 * np.log10(XR[:N1 // 2] / max(XR))) plt.axis([f[0], f[N1 // 2], -300, 0]) plt.grid()
Nfft = 1000 Xfft = np.fft.fft(x, Nfft) # Encontra a FFT Xfft = np.array_split(Xfft, 2)[0] f = np.arange(0, 0.5 * Fs, Fs / Nfft) # Eixo da frequência plt.figure(1, [8, 6]) plt.subplot(311) plt.stem(f, abs(Xfft) / Nfft) # Plota a espectro plt.title('FFT do sinal') # Configura título plt.xlabel('Frequência') plt.ylabel('Magnitude') plt.grid() plt.axis([0, 2 * fc, 0, A**2 / 4]) # Zoom no gráfico from spectrum.window import Window hamming = Window(len(x), name='hamming') f, pxx = sci.periodogram(x, window=hamming.data, fs=Fs, nfft=len(x), scaling='spectrum') pwrest = pxx.max() idx = pxx.argmax() plt.subplot(312) plt.plot(f, pxx) plt.title('Periodograma') plt.xlabel('Frequência') plt.ylabel('Potência (W)') plt.grid() plt.axis([0, 2 * fc, 0, A**2])
#extraindo os arrays das janelas # a classe Window possui um atributo chamado 'data' : array com os valores de amplitude #usaremos esse atributo para trabalhar com os valores da janela from spectrum.window import Window from matplotlib import pyplot as plt import numpy as np N_pontos = 1024 b = Window(N_pontos, name='blackman') #janela do tipo blackman f = Window(N_pontos, name='flattop') #janela do tipo flattop h = Window(N_pontos, name='hamming') #janela do tipo hamming x = np.linspace(0, N_pontos - 1, N_pontos) #eixo horizontal plt.figure(1, [8, 6]) #cria figura vazia, de tamanho 10x7 plt.plot(x, b.data, 'r', x, f.data, 'y', x, h.data, 'b') #plota as linhas das janelas plt.legend(['Blackman', 'Flattop', 'Hamming']) #escolhe as legendas plt.title("Janelas") plt.show()
from spectrum.window import Window from matplotlib import pyplot as plt import numpy as np from scipy import fftpack N_pontos = 1024 b = Window(N_pontos, name='blackman') f = Window(N_pontos, name='flattop') h = Window(N_pontos, name='hamming') fc = 100.0 x = np.linspace(0, N_pontos - 1, N_pontos) y = np.cos(2.0 * np.pi * x * fc) YH = y * h.data #janelamento YH = fftpack.fftshift(np.fft.fft(YH)) # fft YH = 2.0 * np.abs(YH) / N_pontos #normalização YB = y * b.data #janelamento YB = fftpack.fftshift(np.fft.fft(YB)) # fft YB = 2.0 * np.abs(YB) / N_pontos #normalização YF = y * f.data #janelamento YF = fftpack.fftshift(np.fft.fft(YF)) # fft YF = 2.0 * np.abs(YF) / N_pontos # normalização #yt = fftpack.ifft(YF) #plt.plot(yt) plt.plot(x, 20.0 * np.log10(YH / max(YH))) plt.grid() plt.title("Janelamento de um cosseno com Hamming") plt.ylabel("Amplitude (dB)")