4 votos

Generador de ruido blanco a través de un filtro de paso bajo - Autocorrelación de los datos normalizados que caen por debajo de 0 (mostrando una correlación negativa)

Estoy haciendo el siguiente experimento: http://physlab.lums.edu.pk/images/a/ab/Correlation.pdf

Es básicamente un generador de ruido blanco que pasa por un filtro de paso bajo. Se toman tensiones de muestra y se normalizan, y luego se autocorrelacionan utilizando algunos métodos. Se supone que la autocorrelación que utiliza los datos normalizados comienza con un valor de 1 a 0 de retardo (lo que hace) y luego decae exponencialmente a 0 (lo que no hace). Sin embargo, decae por debajo de 0.

También El coeficiente generado automáticamente para un ajuste exponencial (a*np.exp(-(t/b)) + c) (b debería ser = RC), no coincide con la constante RC del filtro paso bajo (R=10kohm, C=0.5 microF, RC=5ms).

Los métodos que estoy utilizando para la autocorrelación son los siguientes f=lista de valores de tensión con la media restada de cada valor, 100.000 muestras @ 10000 S/s

Utilizando la función Correlación incorporada:

def autocorr(f):

    result = np.correlate(f, f, mode='full')

    return result[result.size/2:]

autocorr=autocorr(f)

autocorr /= autocorr[autocorr.argmax()]

enter image description here

Usando FastFourierTransform:

N = len(f)

fvi = np.fft.fft(f) #n=2*N)

acf = np.real( np.fft.ifft( fvi * np.conjugate(fvi) )[:N] )

enter image description here

Trazado utilizando el trazado autocor incorporado de python:

import matplotlib.pyplot as plt

plt.acorr(f)

enter image description here

Que se puede ver no cae por debajo de 0. No puedo averiguar el código exacto que se ejecuta con el plt.acorr(f) ya que no soporta la salida de datos.

Aquí está la exponencial ajustada (mostrando claramente la caída por debajo de 0) función de ajuste =

from scipy.optimize import curve_fit

def func(t,a,b,c):

return a*np.exp(-(t/b)) + c

popt, pcov = curve_fit(func, t, acf)

enter image description here

Sin embargo, la constante autogenerada a partir del ajuste exponencial, que debería ser igual al RC (5ms), resulta en realidad 1,043822ms Además, cuando reduzco el RC en un 50%, el coeficiente calculado se reduce en un 33%. También si cambio la frecuencia de muestreo se reduce el coeficiente

¿Existe una forma de producir la autocorrelación de los datos recogidos, que consiste en un decaimiento exponencial a 0 con la constante de decaimiento como el RC del circuito del filtro paso bajo?

He probado varios valores de RC para el LPF, todos caen por debajo de 0, de hecho cuanto más bajo es el RC, más bajo cae por debajo de 0.

¿Podría estar relacionado con una tensión de offset incorrecta del generador de ruido blanco? He cambiado el offset y ha aumentado el valor más bajo al que cae la autocorrelación, pero no estoy seguro de que si lo vuelvo a ajustar se solucione el problema por completo.

Así que para recapitular, 2 cuestiones

  • La autocorrelación no decae a 0, cae por debajo de 0

  • Coeficiente de decaimiento de la curva exponencial ajustado, no es igual a la constante RC del circuito.

Este hilo Autocorrelación del ruido - correlación negativa Parece estar relacionado con el mismo experimento y la misma cuestión (sin respuesta)

                      **UPDATE 7-3-15:**

Cosas que se han probado: El generador de Ruido Blanco tiene una perilla de umbral para ajustar la frecuencia de umbral. No ha solucionado ninguno de los dos problemas: Ajuste del umbral más alto: Highest threshold setting

Ajuste del umbral más bajo:

Lowest Threshold Setting

La autocorrelación se ajustó al ruido blanco generado por Python y filtrado a través de circuitos de filtro RC de paso bajo simulados (diferentes valores de RC). Esto produjo resultados correctos. Esto me hace pensar que el código utilizado para la autocorrelación es correcto.

He probado el método FFT y la función de correlación incorporada en python para autocorrelacionar los datos y dan los mismos resultados, confirmando también que el código debería estar bien.

Un generador de señales físicas, que genera ondas cuadradas, se probó a través del A2D y se trazó en función del tiempo. El resultado fue correcto con los tiempos correctos que coinciden con la frecuencia de muestreo. Esto confirma que el A2D funciona correctamente.

Ejemplo de onda cuadrada a través de A2D:

enter image description here

Las ondas cuadradas también se pasaron por 2 circuitos RC de paso bajo. Los valores RC correctos se calcularon utilizando un ajuste exponencial. Esto confirma que los circuitos RC funcionan correctamente y que el código utilizado para ajustar las exponenciales también funciona. Sin embargo, se produjo un decaimiento por debajo de 0

Ejemplo de exponencial ajustada sobre onda cuadrada filtrada:

enter image description here

Hay una compensación de voltaje en el generador de ruido blanco, esto se ajustó varias veces (por encima y por debajo de 0V), no arregló las constantes RC exponenciales ajustadas incorrectamente. Afecta al decaimiento de los datos autocorrelacionados, pero no hasta el punto de poder determinar si es la causa del problema.

Trazado de abajo. B = antes del primer cambio de desplazamiento, A = después del primer cambio de desplazamiento, A2-x = después del segundo cambio de desplazamiento. Los RC se corresponden entre sí, por ejemplo, B1, A1, A2-1 tienen el mismo RC, etc.

enter image description here

He comprobado los espectros de potencia de 2 muestras de ruido no filtrado del generador de ruido blanco con los siguientes resultados:

Por favor, ignore las unidades

enter image description here

enter image description here

Es posible que el ruido que se genera no sea en absoluto ruido blanco. Tendré que comprobarlo con más muestras.

Los datos se ajustan a un ruido blanco autocorrelacionado (exponencial decreciente), el problema es que decae más allá de 0 y luego se recupera y las constantes de decaimiento están aproximadamente a un factor de 10 de los valores RC reales de los filtros de paso bajo por los que se filtra el ruido blanco. Actualmente estoy probando los espectros de potencia del ruido blanco (no filtrado ni normalizado).Todos los gráficos de datos son sólo muestras con unas pocas muestras, he corrido más, a muchos para incluir. Gracias a User:Floris para las sugerencias sobre lo que debe mirar.

                      **UPDATE 7-15-15:**

Pues resulta que el problema está en el generador de ruido blanco. Un problema muy extraño.

Añadí un circuito seguidor de tensión antes del circuito RC (para aumentar la corriente disponible) y los resultados mejoraron notablemente. No estoy seguro de si esto es la solución final, ya que hay algunos problemas extraños con el seguidor de voltaje, añadiendo ganancia de voltaje por alguna razón. Probé con otra fuente de ruido blanco antes de usar el seguidor de voltaje y pude lograr una precisión de ~ 90% comparando el valor RC ajustado exponencialmente con el valor RC teórico y ahora puedo igualar eso con el generador de ruido blanco original y el circuito seguidor de voltaje.

Ejemplo de una colección de 10 conjuntos de muestras @ RC=5ms: enter image description here

En comparación con la fuente de ruido blanco "de trabajo": enter image description here

Actualizaré con una respuesta final cuando sepa exactamente qué está pasando y por qué está ocurriendo el problema. Si alguien tiene alguna sugerencia también, muy apreciado.

1 votos

Te recomiendo que empieces por generar algunos sintético ruido blanco para convencerse de que el procesamiento de la señal es correcto. Si lo es, el hecho de que veas una correlación negativa sugiere alguna estructura "no blanca" en tu señal. Este puede ser real... Por cierto, una pregunta muy bien escrita.

0 votos

Lo siento si esto parece estúpido, pero ¿cómo podría generar ruido blanco sintético?

0 votos

¿Esto explicaría también la constante de decaimiento errónea que se genera con el ajuste exponencial?

4voto

Floris Puntos 54054

Una sola medición como ésta tiene mucho ruido, y una señal aleatoria siempre va a tener alguna correlación aleatoria. Definitivamente, no hay que prestar demasiada atención a las cosas que están en la cola de la distribución de la correlación - es todo ruido.

El hecho de que la función incorporada no produzca valores negativos está relacionado con el hecho de que sólo se miran los primeros 10 bins (que es el valor por defecto). Si se trazara todo el rango, se obtendría un valor negativo al igual que los demás - utilice

plt.acorr(f, maxlags=None)

Por cierto, devuelve todos los valores en cuatro variables - si hace

result = plt.acorr(f, maxlags=None)

puede examinar result[0] y result[1] para darte los valores que la función calculó - verás que es similar (idéntico) al que obtienes usando otras funciones. La razón por la que el gráfico es diferente, como he dicho, es que usted no está buscando en el mismo rango de rezagos.

Permítanme demostrar algunos principios. Voy a generar un poco de ruido blanco, filtrarlo con la respuesta de un circuito RC y trazar la autocorrelación varias veces. Vamos a aprender cómo crear ruido blanco (y cómo filtrarlo); que la autocorrelación no será la misma dos veces; que puede ser negativa, incluso si se toma la media de 20; y que la constante de tiempo medida variará bastante. En resumen, saldrás con una mejor idea de esto. Hay mucho más que aprender...

Aquí está el código:

# white noise

import numpy as np
import matplotlib.pyplot as plt
import math
from scipy import stats

def autocorr(f):
    temp = np.correlate(f, f, mode='full')
    mid = temp.size/2
    return temp[mid:]

plt.close('all')

# simulate a simple RC circuit
# V = 1/jwC/(R+1/jwC) = 1/(jwRC+1)
C = 1e-6      # 1 uF
R = 1.0e3     # 1 kOhm
RC = R*C
fs = 100000   # sampling frequency
fc = 1.0 / RC # cutoff frequency
repeats = 100 # number of times experiment is repeated
ns = 10000    # number of samples per repeat (1/10th of a second)
nplot = 500   # number of samples in autocorrelation to plot

t = np.arange(ns)/(1.0*fs) # time corresponding to each sample
fr = fs / (2.0 * ns) # resolution per bin in the FFT

freq =  np.arange(ns) * fr  # frequency bins in FFT
response = np.divide(1, 1j * 2 * math.pi * freq * RC + 1) # complex response per bin

# plot response function:

fn = 4* np.floor(fc / freq[1]) # two octaves above 3dB point
plt.figure()
plt.subplot(2,2,1)
plt.plot(freq[:fn], np.abs(response[:fn]))
plt.xlabel('frequency')
plt.title('Filter response: amplitude')

plt.subplot(2,2,2)
plt.plot(freq[:fn], np.angle(response[:fn], deg=1))
plt.title('Filter response: phase')
plt.ylabel('angle (deg)')
plt.xlabel('frequency')

fa = []  # array where we will store the filtered results
plt.subplot(2,2,3)
for j in range(repeats):
    e = np.random.normal(size=ns)
    # take Fourier transform:
    ff = np.fft.fft(e)
    # roll off the frequencies
    fr = ff * response
    # take inverse FFT:
    filtered = np.fft.ifft(fr)
    ac = autocorr(filtered)
    acNorm = np.abs(ac / ac.max()) # <<< using abs function here: get amplitude
    fa.append(acNorm)
    plt.plot(acNorm[:nplot])

plt.xlabel('correlation distance')
plt.title('Autocorrelation: result of %d samples'%repeats) 
plt.show()

# calculate the mean of the repeated samples:
repeatedMean = np.mean(fa, axis=0)

plt.subplot(2,2,4)
plt.semilogy(repeatedMean[:nplot])
plt.title('mean of %d repeats'%repeats)
plt.xlabel('correlation distance')
plt.show()

# fit an exponential to the data
# anything beyond the first 20 points does not make much sense - contains no useful information

# fit an exponential to the data
# anything beyond the first 20 points does not make much sense - contains no useful information

nfit = fs*RC  # <<<< added
slopes = []
plt.figure()
for j in range(repeats):
    slope, intercept, r_value, p_value, std_err = stats.linregress(t[:nfit], np.log(fa[j][:nfit]))
    plt.plot(t[:nfit], fa[j][:nfit])
    slopes.append(slope)
plt.title('autocorrelation used for fitting') # <<< fixed typo
plt.xlabel('correlation time')
plt.show()
print 'mean time constant is %.2f ms'%np.mean(np.divide(-1000,slopes)) # <<< changed
print 'standard deviation is %.3f ms'%np.std(np.divide(1000, slopes))  # <<< changed

Y aquí están las parcelas que produce:

enter image description here

enter image description here

La constante de tiempo derivada de estos ajustes (inversa de la pendiente) promediada sobre 100 ajustes fue de 1,01 ± 0,15 ms - consistente con la constante de tiempo de 1,0 ms que estaba implícita en la elección de componentes en mi código (1 kOhm y 1 uF).

Juega con el código y dime si esto te aclara las cosas.

0 votos

Gracias por la respuesta en profundidad. Lo revisaré hoy mismo.

0 votos

Puedo preguntar, ¿el código que estás usando para aplicar el filtro de paso bajo es simplemente: 1-Aplicar la Transformada de Fourier a los datos de ruido para llevarlos al dominio de la frecuencia? 2-Eliminar las frecuencias requeridas (usando su variable de "respuesta" previamente definida. luego 3-Aplicar la Transformada de Fourier inversa para llevar la señal de vuelta al dominio del tiempo?

0 votos

Sí, eso es exactamente lo que estoy haciendo. Hay todo tipo de funciones de filtro incorporadas (Butterworth, etc.) que son filtros "mejores" pero que no imitan tan bien la respuesta RC "imperfecta" (puede que existan y no los conozco...).

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X