Dla tych, którzy próbują nawiązać połączenie między SNR z normalną zmienną losową generowaną przez numpy:
[1]
, gdzie należy pamiętać, że P to moc średnia .
Lub w dB:
[2]
W tym przypadku mamy już sygnał i chcemy wygenerować szum, aby uzyskać pożądany SNR.
Chociaż szum może mieć różne smaki w zależności od tego, co modelujesz, dobrym początkiem (szczególnie w przypadku tego przykładu radioteleskopu) jest Addytywny Biały Szum Gaussowski (AWGN) . Jak stwierdzono w poprzednich odpowiedziach, aby modelować AWGN, należy dodać zerową średnią gaussowską zmienną losową do oryginalnego sygnału. Wariancja tej zmiennej losowej wpłynie na średnią moc szumów.
Dla losowej zmiennej Gaussa X, średnia moc
, znana również jako drugi moment , wynosi
[3] 
Więc dla białego szumu,
a średnia moc jest równa wariancji
.
Podczas modelowania tego w Pythonie możesz:
1. Obliczyć wariancję na podstawie pożądanego SNR i zestawu istniejących pomiarów, co zadziała, jeśli spodziewasz się, że pomiary będą miały dość spójne wartości amplitudy.
2. Alternatywnie, możesz ustawić moc szumu na znanym poziomie, aby dopasować coś takiego jak szum odbiornika. Szum odbiornika można zmierzyć, kierując teleskop w wolną przestrzeń i obliczając średnią moc.
Tak czy inaczej, ważne jest, aby upewnić się, że dodajesz szum do sygnału i bierzesz średnie w przestrzeni liniowej, a nie w jednostkach dB.
Oto kod generujący sygnał i wykreślający napięcie, moc w watach i moc w 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()

Oto przykład dodawania AWGN na podstawie pożądanego SNR:
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()

A oto przykład dodawania AWGN na podstawie znanej mocy szumów:
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()
