Для тех, кто пытается установить связь между SNR и нормальной случайной величиной, сгенерированной numpy:
[1]
, где важно помнить, что P - это средняя мощность.
Или в дБ:
[2]
В этом случае у нас уже есть сигнал, и мы хотим сгенерировать шум, чтобы получить желаемое SNR.
Хотя шум может иметь разные вкусы в зависимости от того, что вы моделируете, хорошим началом (особенно для этого примера радиотелескопа) является аддитивный белый гауссовский шум (AWGN) . Как указано в предыдущих ответах, для моделирования AWGN вам необходимо добавить гауссовскую случайную величину с нулевым средним к исходному сигналу. Дисперсия этой случайной величины повлияет на среднюю мощность шума.
Для гауссовой случайной величины X средняя мощность
, также известная как второй момент , равна
[3] 
Итак, для белого шума
средняя мощность равна дисперсии
.
При моделировании этого на python вы можете:
1. Вычислить дисперсию на основе желаемого отношения сигнал / шум и набора существующих измерений, что будет работать, если вы ожидаете, что ваши измерения будут иметь достаточно согласованные значения амплитуды.
2. В качестве альтернативы вы можете установить мощность шума на известный уровень, чтобы соответствовать чему-то вроде шума приемника. Шум приемника можно было измерить, направив телескоп в свободное пространство и вычислив среднюю мощность.
В любом случае, важно убедиться, что вы добавляете шум в свой сигнал и принимаете средние значения в линейном пространстве, а не в единицах дБ.
Вот код для генерации сигнала и графика напряжения, мощности в ваттах и мощности в дБ:
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()

Вот пример добавления AWGN на основе желаемого 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()

А вот пример добавления AWGN на основе известной мощности шума:
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()
