Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
@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()
Ejemplo n.º 3
0
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])
Ejemplo n.º 4
0
#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()
Ejemplo n.º 5
0
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)")