Para aquellos que intentan hacer la conexión entre SNR y una variable aleatoria normal generada por numpy:
[1]
, donde es importante tener en cuenta que P es la potencia promedio .
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 dependiendo de lo que esté modelando, un buen comienzo (especialmente para este ejemplo de radiotelescopio) es el ruido blanco gaussiano aditivo (AWGN) . Como se indicó en las respuestas anteriores, para modelar AWGN debe agregar una variable aleatoria gaussiana de media cero a su señal original. La varianza de esa variable aleatoria afectará la potencia de ruido promedio .
Para una variable aleatoria gaussiana X, la potencia promedio
, también conocida como segundo momento , es
[3] 
Entonces, para el ruido blanco,
la potencia promedio es igual a la varianza
.
Al modelar esto en Python, puede:
1. Calcular la varianza en función de una SNR deseada y un conjunto de medidas existentes, lo que funcionaría si espera que sus medidas tengan valores de amplitud bastante consistentes.
2. Alternativamente, puede establecer la potencia de ruido a un nivel conocido para igualar algo como el ruido del receptor. El ruido del receptor se puede medir apuntando el telescopio hacia el 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:
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()

A continuación, se muestra un ejemplo para agregar AWGN en función de una SNR deseada:
target_snr_db = 20
sig_avg_watts = np.mean(x_watts)
sig_avg_db = 10 * np.log10(sig_avg_watts)
noise_avg_db = sig_avg_db - target_snr_db
noise_avg_watts = 10 ** (noise_avg_db / 10)
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(noise_avg_watts), len(x_watts))
y_volts = x_volts + noise_volts
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()
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:
target_noise_db = 10
target_noise_watts = 10 ** (target_noise_db / 10)
mean_noise = 0
noise_volts = np.random.normal(mean_noise, np.sqrt(target_noise_watts), len(x_watts))
y_volts = x_volts + noise_volts
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()
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()
