Tengo acceso a numpy y scipy y desea crear un simple FFT de un conjunto de datos. Tengo dos listas, una que es y de valores y el otro es el de las marcas de tiempo de los valores de y.

¿Cuál es la forma más sencilla de alimentar a estas listas en una scipy o numpy método y de la parcela resultante de la FFT?

He buscado ejemplos, pero todos ellos se basan en la creación de un conjunto de datos falsos con un determinado número de puntos de datos, y la frecuencia, etc. y no muestra realmente cómo hacerlo con sólo un conjunto de datos y las correspondientes marcas de tiempo.

He probado el siguiente ejemplo:

from scipy.fftpack import fft
# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
import matplotlib.pyplot as plt
plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
plt.grid()
plt.show()

Pero cuando voy a cambiar el argumento de la fft para mi conjunto de datos y de la trama que tengo muy extraño resultados, parece que la escala de la frecuencia puede ser apagado. yo no estoy seguro.

Aquí es un pastebin de los datos que yo estoy tratando de FFT

http://pastebin.com/0WhjjMkb
http://pastebin.com/ksM4FvZS

Cuando hago una fft sobre todo esto sólo tiene un enorme pico en cero y nada más

Aquí está mi código:

## Perform FFT WITH SCIPY
signalFFT = fft(yInterp)

## Get Power Spectral Density
signalPSD = np.abs(signalFFT) ** 2

## Get frequencies corresponding to signal PSD
fftFreq = fftfreq(len(signalPSD), spacing)

## Get positive half of frequencies
i = fftfreq>0

##
plt.figurefigsize=(8,4));
plt.plot(fftFreq[i], 10*np.log10(signalPSD[i]));
#plt.xlim(0, 100);
plt.xlabel('Frequency Hz');
plt.ylabel('PSD (dB)')

espacio es igual a xInterp[1]-xInterp[0]

  • nos muestran lo has probado, ¿cómo se produjo el error, y los ejemplos que usted está trabajando.
  • he publicado el ejemplo, he intentado así como lo que yo pensaba de ella, creo que estoy confundido sobre cómo trazar la salida correctamente.
  • eso es un gran ejemplo, pero ¿qué es exactamente el problema? ese código funciona muy bien para mí. es la trama simplemente no se muestran?
  • es decir, qué tipo de argumentos se está utilizando (tenemos que ver al menos algunos de sus datos)
  • he añadido el pastebin de la x y el eje y, los datos de x es en segundos y los datos y es sólo una lectura del sensor. Cuando pongo estas listas de datos en la fft ejemplo sólo tiene un enorme pico en cero
InformationsquelleAutor user3123955 | 2014-09-09

6 Comentarios

  1. 76

    Así que me quede un funcionalmente equivalente de la forma de su código en un IPython notebook:

    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    import scipy.fftpack
    
    # Number of samplepoints
    N = 600
    # sample spacing
    T = 1.0 / 800.0
    x = np.linspace(0.0, N*T, N)
    y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
    yf = scipy.fftpack.fft(y)
    xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
    
    fig, ax = plt.subplots()
    ax.plot(xf, 2.0/N * np.abs(yf[:N//2]))
    plt.show()

    Me pongo lo que creo que es muy razonable salida.

    Trazado de una transformada Rápida de Fourier en Python

    Han pasado más de lo que quisiera admitir, desde que yo estaba en la escuela de ingeniería pensando en el procesamiento de la señal, pero los picos en los 50 y los 80 son exactamente lo que yo esperaría. Así que ¿cuál es el problema?

    En respuesta a los datos en bruto y los comentarios de ser publicado

    El problema aquí es que usted no tiene periódica de datos. Usted siempre debe inspeccionar los datos de los que se alimentan en cualquier algoritmo para asegurarse de que es apropiado.

    import pandas
    import matplotlib.pyplot as plt
    #import seaborn
    %matplotlib inline
    
    # the OP's data
    x = pandas.read_csv('http://pastebin.com/raw.php?i=ksM4FvZS', skiprows=2, header=None).values
    y = pandas.read_csv('http://pastebin.com/raw.php?i=0WhjjMkb', skiprows=2, header=None).values
    fig, ax = plt.subplots()
    ax.plot(x, y)

    Trazado de una transformada Rápida de Fourier en Python

    • No es que el ejemplo es malo, lo que no sé cómo tomar eso y aplicarlo a mis datos.
    • a la derecha. es por eso que necesitamos ver sus datos y cómo se produce un error si nos vas a ayudar.
    • voy a hacer un pastebin y editar el post original muy poco
    • he añadido el pastebin
    • eso es genial. ahora, ¿cómo está usted usando los datos? dónde está tu código fallando?
    • he añadido mi código, en mi post original declaro que parece sólo estar mostrando un gran repunte a 0 Hz, la cual, si se hace una gráfica de los datos, no parece correcto
    • lo siento soy incorrecto, en lugar de ver un pico a cero (lo que yo vi con numpy.fft) estoy viendo nada, no parece nada de la trama
    • por supuesto que no hay picos. mira tus datos de nuevo, y mis ediciones a la respuesta.
    • que es una discontinuidad en los datos debido a que el sensor disconecting.
    • así que ¿qué se puede esperar cualquier algoritmo de la FFT para hacer acerca de eso? usted necesita para limpiar sus datos.
    • sí, creo que es un tema aparte que necesito dirección, gracias por la ayuda
    • Necesito hacer esto en Java, Pero yo no entiendo de Python, ya que mi FFT código, pero no sé cómo parcela.
    • Puede usted por favor ver la pregunta de la mina? aquí está el enlace: stackoverflow.com/questions/29888457/…
    • La declaración [:N/2] debe [:N//2] para evitar un mismo mensaje de advertencia. Los valores de punto flotante no debe ser índices. En 2.x N/2 creado un int. En 3.x N/2 crea un flotador. N//2 crea la int espera que en 2.x
    • gracias. He actualizado la respuesta
    • no debería la amplitud a la frecuencia de 50 Hz ser 1 y a la frecuencia 80 Hz ser 0.5?

  2. 19

    Lo importante acerca de la fft es que sólo puede aplicarse a los datos en los que la marca de tiempo es uniforme (es decir, muestreo uniforme en el tiempo, como lo han mostrado arriba).

    En el caso de muestreo no uniforme, por favor, utilice una función para el ajuste de los datos. Hay varios tutoriales y funciones a elegir:

    https://github.com/tiagopereira/python_tips/wiki/Scipy%3A-curve-fitting
    http://docs.scipy.org/doc/numpy/reference/generated/numpy.polyfit.html

    Si el ajuste no es una opción, usted puede utilizar directamente algún tipo de interpolación la interpolación de los datos de un muestreo uniforme:

    https://docs.scipy.org/doc/scipy-0.14.0/reference/tutorial/interpolate.html

    Cuando usted tiene uniforme de las muestras, usted sólo tiene que wory sobre el tiempo delta (t[1] - t[0]) de sus muestras. En este caso, usted puede utilizar directamente la fft funciones

    Y    = numpy.fft.fft(y)
    freq = numpy.fft.fftfreq(len(y), t[1] - t[0])
    
    pylab.figure()
    pylab.plot( freq, numpy.abs(Y) )
    pylab.figure()
    pylab.plot(freq, numpy.angle(Y) )
    pylab.show()

    Esto debería resolver su problema.

    • He interpolado mis datos para un espaciado uniforme, me Puedes decir exactamente lo que el fftfreq hace? ¿por qué necesita mi eje x? ¿por qué trama el abs de la y y el ángulo? Es el ángulo de la fase? ¿Cuál es la fase relativa a? Cuando hago esto con mis datos sólo tiene un pico gigante en 0Hz y colas muy rápido, pero yo soy de la alimentación de datos, que no tienen un desfase constante (tengo que hacer un gran paso de banda de los datos con los bordes 0.15 Gz a 12Hz para deshacerse de la constante de desplazamiento, mis datos no debe ser mayor de 4 Hz de todos modos por lo que la banda debería hacerme perder información).
    • 1. fftfreq le da las componentes de frecuencia correspondiente a sus datos. Si usted parcela freq verá que el eje x no es una función que sigue aumentando. Usted tendrá que asegurarse de que usted tiene el derecho de componentes de frecuencia en el eje de las x. Usted puede mirar en el manual: docs.scipy.org/doc/numpy/reference/generated/…
    • 2. La mayoría de la gente le gusta mirar la magnitud y la fase de la fft. Es difícil de explicar en una sola frase lo que la fase de información va a decir, pero todo lo que puedo decir es que es significativa cuando se combinan las señales. Cuando se combinan las señales de la misma frecuencia que están en fase amplifican, mientras que cuando están fuera de fase de 180 grados, que se atenuará. Esto es importante cuando el diseño de amplificadores o cualquier cosa que haya retroalimentación.
    • 3. Por lo general, su frecuencia más baja tendrá prácticamente cero de la fase, y es en referencia a esto. Cuando las señales se mueven a través de su sistema, cada frecuencia se mueve con una diferente velocidad. Esta es la velocidad de fase. La fase de la trama le da esta información. No sé qué sistema se está trabajando, y no puede dar una respuesta definitiva. Para tales preguntas, es mejor leer un control de retroalimentación, analógico elecrronics, procesamiento digital de señales, electromagentic la teoría de campo, etc., o algo que es más específico para su sistema.
    • 4. En lugar de utilizar su de datos, ¿por qué no empezar por la generación de sus propias señales: t = linspace(0, 10, 1000); ys = [ (1.0/i)*sin(i*t) for i in arange(10)]; y = reduce(lambda m, n: m+n, ys). Luego de la parcela de cada uno de los ys y el total de y y obtener la fft de cada componente. Usted ganará la confianza con su programación. Entonces usted puede juzgar la autenticidad de su resultado. Si la señal que usted está tratando de analizar es el primero que he tomado la fft de entonces siempre vas a sentir que estás haciendo algo mal …
  3. 8

    El alto pico que tienes es debido a la DC (no varían, es decir, freq = 0) de la porción de la señal. Es un problema de escala. Si usted desea ver los no-DC contenido de frecuencia, para la visualización, puede que necesite parcela a partir de la compensación 1 no desde el offset 0 de la FFT de la señal.

    Modificar el ejemplo anterior, por @PaulH

    import numpy as np
    import matplotlib.pyplot as plt
    import scipy.fftpack
    
    # Number of samplepoints
    N = 600
    # sample spacing
    T = 1.0 / 800.0
    x = np.linspace(0.0, N*T, N)
    y = 10 + np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
    yf = scipy.fftpack.fft(y)
    xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
    
    plt.subplot(2, 1, 1)
    plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
    plt.subplot(2, 1, 2)
    plt.plot(xf[1:], 2.0/N * np.abs(yf[0:N/2])[1:])

    La salida de las parcelas:
    Trazado de una transformada Rápida de Fourier en Python

    De otra manera, es para visualizar los datos en escala logarítmica:

    Uso:

    plt.semilogy(xf, 2.0/N * np.abs(yf[0:N/2]))

    Mostrará:
    Trazado de una transformada Rápida de Fourier en Python

    • Lo del eje x de la unidad? Hz?
    • Sí, es en Hz. En el código, la definición de xf mapas de la fft cestos de frecuencias.
    • Bueno! Y, ¿sobre el eje y? Amplitud? Muchas gracias hesham_EE
    • Sí, eje y es el valor absoluto de la fft compleja. Observe el uso de np.abs()
  4. 5

    Sólo como un complemento a las respuestas ya dadas, me gustaría señalar que, a menudo, es importante jugar con el tamaño de los contenedores de la FFT. Tendría sentido para probar un montón de valores y escoger la que tenga más sentido para su aplicación. A menudo, es en el mismo orden de magnitud del número de muestras. Esto fue asumido por la mayoría de las respuestas dadas, y produce grandes y resultados razonables. En caso de que uno quiere explorar que, aquí está mi versión de código:

    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    import scipy.fftpack
    fig = plt.figure(figsize=[14,4])
    N = 600           # Number of samplepoints
    Fs = 800.0
    T = 1.0 / Fs      # N_samps*T (#samples x sample period) is the sample spacing.
    N_fft = 80        # Number of bins (chooses granularity)
    x = np.linspace(0, N*T, N)     # the interval
    y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)   # the signal
    # removing the mean of the signal
    mean_removed = np.ones_like(y)*np.mean(y)
    y = y - mean_removed
    # Compute the fft.
    yf = scipy.fftpack.fft(y,n=N_fft)
    xf = np.arange(0,Fs,Fs/N_fft)
    ##### Plot the fft #####
    ax = plt.subplot(121)
    pt, = ax.plot(xf,np.abs(yf), lw=2.0, c='b')
    p = plt.Rectangle((Fs/2, 0), Fs/2, ax.get_ylim()[1], facecolor="grey", fill=True, alpha=0.75, hatch="/", zorder=3)
    ax.add_patch(p)
    ax.set_xlim((ax.get_xlim()[0],Fs))
    ax.set_title('FFT', fontsize= 16, fontweight="bold")
    ax.set_ylabel('FFT magnitude (power)')
    ax.set_xlabel('Frequency (Hz)')
    plt.legend((p,), ('mirrowed',))
    ax.grid()
    ##### Close up on the graph of fft#######
    # This is the same histogram above, but truncated at the max frequence + an offset. 
    offset = 1    # just to help the visualization. Nothing important.
    ax2 = fig.add_subplot(122)
    ax2.plot(xf,np.abs(yf), lw=2.0, c='b')
    ax2.set_xticks(xf)
    ax2.set_xlim(-1,int(Fs/6)+offset)
    ax2.set_title('FFT close-up', fontsize= 16, fontweight="bold")
    ax2.set_ylabel('FFT magnitude (power) - log')
    ax2.set_xlabel('Frequency (Hz)')
    ax2.hold(True)
    ax2.grid()
    plt.yscale('log')

    la salida de las parcelas:
    Trazado de una transformada Rápida de Fourier en Python

  5. 1

    Ya hay grandes soluciones en esta página, pero todos han asumido el conjunto de datos es uniformemente/muestreada uniformemente distribuidos. Voy a intentar dar un ejemplo más general de una muestra aleatoria de datos. Yo también uso este tutorial de MATLAB como un ejemplo:

    Añadiendo los módulos necesarios:

    import numpy as np
    import matplotlib.pyplot as plt
    import scipy.fftpack
    import scipy.signal

    La generación de datos de ejemplo:

    N = 600 # number of samples
    t = np.random.uniform(0.0, 1.0, N) # assuming the time start is 0.0 and time end is 1.0
    S = 1.0 * np.sin(50.0 * 2 * np.pi * t) + 0.5 * np.sin(80.0 * 2 * np.pi * t) 
    X = S + 0.01 * np.random.randn(N) # adding noise

    Ordenar el conjunto de datos:

    order = np.argsort(t)
    ts = np.array(t)[order]
    Xs = np.array(X)[order]

    De remuestreo:

    T = (t.max() - t.min()) / N # average period 
    Fs = 1 / T # average sample rate frequency
    f = Fs * np.arange(0, N // 2 + 1) / N; # resampled frequency vector
    X_new, t_new = scipy.signal.resample(Xs, N, ts)

    el trazado de los datos y vuelven a muestrear datos:

    plt.xlim(0, 0.1)
    plt.plot(t_new, X_new, label="resampled")
    plt.plot(ts, Xs, label="org")
    plt.legend()
    plt.ylabel("X")
    plt.xlabel("t")

    Trazado de una transformada Rápida de Fourier en Python

    ahora el cálculo de la fft:

    Y = scipy.fftpack.fft(X_new)
    P2 = np.abs(Y / N)
    P1 = P2[0 : N // 2 + 1]
    P1[1 : -2] = 2 * P1[1 : -2]
    plt.ylabel("Y")
    plt.xlabel("f")
    plt.plot(f, P1)

    Trazado de una transformada Rápida de Fourier en Python

    • Yo no estoy viendo nada en la documentación que sugiere resample maneja no uniforme de la muestra de veces. Se acepta un parámetro de tiempo (que no se utiliza en el ejemplo), pero que parece asumir muestra uniforme veces así.
    • href=»https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.resample_poly.html» >este ejemplo podría ayudar
    • Editado el código. agradecería si pudieras echar un vistazo y quiero saber si esto está bien ahora.
    • ‘scipy.de la señal.remuestrear` se usa el método de la FFT para remuestrear los datos. No tiene sentido utilizar para volver a muestrear no uniforme de los datos para conseguir un uniforme de la FFT.
    • es sólo una de las opciones disponibles, y no necesariamente la mejor. Voy a buscar a los demás, compare y se va a editar mi post. gracias por tus comentarios.
    • Parece que fui demasiado ingenuo aquí. Hay ya algunas bibliotecas disponibles: 1. el nfft biblioteca que parece ser un contenedor NFFT 2. el pyNFFT y 3. PyNUFFT
    • bueno, en realidad mi solución anterior no es tan horrible después de todo. Interpolación de datos parece ser el enfoque legítimo. Por ejemplo esta MATLAB ejemplo y este Mathematica ejemplo han utilizado el mismo método.
    • scipy.interpolate, sklearn.utils.resample, pandas.DataFrame.resample, numpy.interp son algunos de los otros interpolación/remuestreo de las opciones disponibles.
    • Hay ventajas y desventajas para todos los métodos que he dado (aunque hay que hacer notar que sklearn.utils.resample no realizar la interpolación). Si quieres discutir las opciones disponibles para encontrar las frecuencias de una forma irregular señal muestreada, o los méritos de los diferentes tipos de interpolación, por favor, inicie otra pregunta. Ambos son temas interesantes, pero mucho más allá del alcance de las respuestas sobre cómo trazar una FFT.

  6. 1

    He disponer de construir una función que se ocupa de trazado de la FFT real de las señales. En mi función allí es la amplitud REAL de la señal (de nuevo, debido a la asunción de la señal real, lo que significa que la simetría…):

    import matplotlib.pyplot as plt
    import numpy as np
    import warnings
    def fftPlot(sig, dt=None, block=False, plot=True):
    # here it's assumes analytic signal (real signal...)- so only half of the axis is required
    if dt is None:
    dt = 1
    t = np.arange(0, sig.shape[-1])
    xLabel = 'samples'
    else:
    t = np.arange(0, sig.shape[-1]) * dt
    xLabel = 'freq [Hz]'
    if sig.shape[0] % 2 != 0:
    warnings.warn("signal prefered to be even in size, autoFixing it...")
    t = t[0:-1]
    sig = sig[0:-1]
    sigFFT = np.fft.fft(sig) / t.shape[0]  # divided by size t for coherent magnitude
    freq = np.fft.fftfreq(t.shape[0], d=dt)
    # plot analytic signal - right half of freq axis needed only...
    firstNegInd = np.argmax(freq < 0)
    freqAxisPos = freq[0:firstNegInd]
    sigFFTPos = 2 * sigFFT[0:firstNegInd]  # *2 because of magnitude of analytic signal
    if plot:
    plt.figure()
    plt.plot(freqAxisPos, np.abs(sigFFTPos))
    plt.xlabel(xLabel)
    plt.ylabel('mag')
    plt.title('Analytic FFT plot')
    plt.show(block=block)
    return sigFFTPos, freqAxisPos
    if __name__ == "__main__":
    dt = 1 / 1000
    f0 = 1 / dt / 4
    t = np.arange(0, 1 + dt, dt)
    sig = np.sin(2 * np.pi * f0 * t)
    fftPlot(sig, dt=dt)
    fftPlot(sig)
    t = np.arange(0, 1 + dt, dt)
    sig = np.sin(2 * np.pi * f0 * t) + 10 * np.sin(2 * np.pi * f0 / 2 * t)
    fftPlot(sig, dt=dt, block=True)

Dejar respuesta

Please enter your comment!
Please enter your name here