Después de consultar expertos en el tema, programadores de deferentes ramas y profesores hemos dado con la solución al dilema y la plasmamos en este post.
Solución:
Puedes generar un ruido arrayy añádelo a tu señal
import numpy as np
noise = np.random.normal(0,1,100)
# 0 is the mean of the normal distribution you are choosing from
# 1 is the standard deviation of the normal distribution
# 100 is the number of elements you get in array noise
… Y para aquellos que, como yo, están muy temprano en su curva de aprendizaje,
import numpy as np
pure = np.linspace(-1, 1, 100)
noise = np.random.normal(0, 1, 100)
signal = pure + noise
Para aquellos que intentan establecer la conexión entre SNR y una variable aleatoria normal generada por numpy:
[1]
O en dB:
[2]
En este caso, ya tenemos una señal y queremos generar ruido para darnos una SNR deseada.
Si bien el ruido puede tener diferentes sabores según lo que esté modelando, un buen comienzo (especialmente para este ejemplo de radiotelescopio) es el ruido gaussiano blanco aditivo (AWGN). Como se indicó en las respuestas anteriores, para modelar AWGN necesita agregar una variable aleatoria gaussiana de media cero a su señal original. La varianza de esa variable aleatoria afectará la promedio potencia de ruido
Para una variable aleatoria gaussiana X, la potencia promedio también conocido como el segundo momento, es
[3]
Así que para el ruido blanco, y la potencia media es entonces igual a la varianza .
Al modelar esto en python, puede
1. Calcule la varianza en función de una SNR deseada y un conjunto de mediciones existentes, lo que funcionaría si espera que sus mediciones tengan valores de amplitud bastante consistentes.
2. Alternativamente, puede configurar la potencia del ruido a un nivel conocido para que coincida con algo como el ruido del receptor. El ruido del receptor podría medirse apuntando el telescopio al espacio libre y calculando la potencia promedio.
De cualquier manera, es importante asegurarse de agregar ruido a su señal y tomar promedios en el espacio lineal y no en unidades de dB.
Aquí hay un código para generar una señal y trazar el voltaje, la potencia en vatios y la potencia en dB:
# Signal Generation
# matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(1, 100, 1000)
x_volts = 10*np.sin(t/(2*np.pi))
plt.subplot(3,1,1)
plt.plot(t, x_volts)
plt.title('Signal')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()
x_watts = x_volts ** 2
plt.subplot(3,1,2)
plt.plot(t, x_watts)
plt.title('Signal Power')
plt.ylabel('Power (W)')
plt.xlabel('Time (s)')
plt.show()
x_db = 10 * np.log10(x_watts)
plt.subplot(3,1,3)
plt.plot(t, x_db)
plt.title('Signal Power in dB')
plt.ylabel('Power (dB)')
plt.xlabel('Time (s)')
plt.show()
Aquí hay un ejemplo para agregar AWGN basado en una SNR deseada:
# Adding noise using target SNR
# Set a target SNR
target_snr_db = 20
# Calculate signal power and convert to dB
sig_avg_watts = np.mean(x_watts)
sig_avg_db = 10 * np.log10(sig_avg_watts)
# Calculate noise according to [2] then convert to watts
noise_avg_db = sig_avg_db - target_snr_db
noise_avg_watts = 10 ** (noise_avg_db / 10)
# Generate an sample of white noise
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(noise_avg_watts), len(x_watts))
# Noise up the original signal
y_volts = x_volts + noise_volts
# Plot signal with noise
plt.subplot(2,1,1)
plt.plot(t, y_volts)
plt.title('Signal with noise')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()
# Plot in dB
y_watts = y_volts ** 2
y_db = 10 * np.log10(y_watts)
plt.subplot(2,1,2)
plt.plot(t, 10* np.log10(y_volts**2))
plt.title('Signal with noise (dB)')
plt.ylabel('Power (dB)')
plt.xlabel('Time (s)')
plt.show()
Y aquí hay un ejemplo para agregar AWGN basado en una potencia de ruido conocida:
# Adding noise using a target noise power
# Set a target channel noise power to something very noisy
target_noise_db = 10
# Convert to linear Watt units
target_noise_watts = 10 ** (target_noise_db / 10)
# Generate noise samples
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(target_noise_watts), len(x_watts))
# Noise up the original signal (again) and plot
y_volts = x_volts + noise_volts
# Plot signal with noise
plt.subplot(2,1,1)
plt.plot(t, y_volts)
plt.title('Signal with noise')
plt.ylabel('Voltage (V)')
plt.xlabel('Time (s)')
plt.show()
# Plot in dB
y_watts = y_volts ** 2
y_db = 10 * np.log10(y_watts)
plt.subplot(2,1,2)
plt.plot(t, 10* np.log10(y_volts**2))
plt.title('Signal with noise')
plt.ylabel('Power (dB)')
plt.xlabel('Time (s)')
plt.show()
Aquí puedes ver las reseñas y valoraciones de los usuarios
Recuerda que puedes optar por la opción de agregar una reseña .