Для своей дипломной работы я создаю инструментарий. Я запрограммировал несколько функций, но одна из них не работает так, как я ожидаю.
Сначала я создал функцию ниже. Он создает случайный белый шум, строит его в области частот и мощности, «предполагая», что он уже находится в этой области (для целей моделирования). Затем обратное преобразование Фурье применяется для получения смоделированного сигнала, после чего применяется регулярное преобразование Фурье для получения белого шума, который я создал сам. Этот последний шаг заключается в проверке того, ведет ли себя функция так, как я ожидаю, и это так.
def white_noise(n: int, N: int, slope: int = grad):
x = np.linspace(1, 100, n)
slope_loglog = (10 ** (slope * np.log10(x) + 1))
whitenoise = rnd.rand(n, N)
whitenoise_power = whitenoise ** 2 # quadratic of the white noise to retrieve the power spectrum
whitenoise_filtered = (whitenoise_power.T * slope_loglog).T
whitenoise_signal = fft.ifft(whitenoise_filtered)
whitenoise_retransformed = fft.fft(whitenoise_signal)
return whitenoise, whitenoise_filtered, whitenoise_signal, whitenoise_retransformed, slope_loglog
После этого я проверил на графике результаты, совпадают ли мои сгенерированный и дважды преобразованный белый шум. Как видно на рисунке ниже, они идентичны, что подтверждает мой сценарий.
Теперь моя проблема показывает. В модифицированной версии скрипта выше (см. Ниже). Мой сгенерированный и дважды преобразованный белый шум не ведет себя одинаково. Модифицированный скрипт добавляет функциональность modified_roll
(небольшая функция, которая переворачивает функцию на себя, имитируя смещение во времени).
def white_noise_signal_shift(n: int, N: int, num: int, shift: int, operations: int):
whitenoise, whitenoise_filtered, whitenoise_signal = white_noise(n, N)[:3]
# only showing the selected arrays
arrays_to_select = random_arrays(N, num)
selected_whitenoise = whitenoise[:, arrays_to_select].copy()
selected_whitenoise_filtered = whitenoise_filtered[:, arrays_to_select].copy()
selected_whitenoise_signal = whitenoise_signal[:, arrays_to_select].copy()
# shifting the signal as a field of different refractive index would do
if operations == 0:
shifted_signal = selected_whitenoise_signal
else:
shifted_signal = modified_roll(selected_whitenoise_signal.copy(), shift, operations)
# fourier transform back to the power frequency domain
shifted_whitenoise = fft.fft(shifted_signal)
return selected_whitenoise, selected_whitenoise_filtered, selected_whitenoise_signal, shifted_signal, \
shifted_whitenoise
Как можно видеть, заполнение white_noise_signal_shift(n, N, N, 0, 0)
, как это должно быть равно white_noise(n, N)
(если вы используете numpy.random.seed())
. Однако для большого N
это не так, Это можно увидеть на рисунке ниже. В обоих сценариях шаг возврата в частотно-частотную область равен fft.fft("signal")
, и, как можно видеть, сигналы на рисунке также идентичны. Что я делаю не так?
Скопируйте это, чтобы получить результат от второй цифры.
import matplotlib.pyplot as plt
import numpy as np
import numpy.fft as fft
import numpy.random as rnd
grad = -5/3.
def white_noise(n: int, N: int, slope: int = grad):
x = np.linspace(1, 100, n)
slope_loglog = (10 ** (slope * np.log10(x) + 1))
whitenoise = rnd.rand(n, N)
whitenoise_power = whitenoise ** 2 # quadratic of the white noise to retrieve the power spectrum
whitenoise_filtered = (whitenoise_power.T * slope_loglog).T
whitenoise_signal = fft.ifft(whitenoise_filtered)
whitenoise_retransformed = fft.fft(whitenoise_signal)
return whitenoise, whitenoise_filtered, whitenoise_signal, whitenoise_retransformed, slope_loglog
# random array selection
def random_arrays(N: int, num: int):
res = np.asarray(range(N))
rnd.shuffle(res)
return res[:num]
def modified_roll(inp, shift: int, operations: int):
count = 0
array = inp[:]
array_rolled = array.copy()
for k in range(operations):
count += shift
array = np.roll(array, shift, axis=0)
array[:count] = 0
array_rolled += array
out = array_rolled / operations
return out
def white_noise_signal_shift(n: int, N: int, num: int, shift: int, operations: int):
whitenoise, whitenoise_filtered, whitenoise_signal = white_noise(n, N)[:3]
# only showing the selected arrays
arrays_to_select = random_arrays(N, num)
selected_whitenoise = whitenoise[:, arrays_to_select].copy()
selected_whitenoise_filtered = whitenoise_filtered[:, arrays_to_select].copy()
selected_whitenoise_signal = whitenoise_signal[:, arrays_to_select].copy()
# shifting the signal as a field of different refractive index would do
if operations == 0:
shifted_signal = selected_whitenoise_signal
else:
shifted_signal = modified_roll(selected_whitenoise_signal.copy(), shift, operations)
# fourier transform back to the power frequency domain
shifted_whitenoise = fft.fft(shifted_signal)
return selected_whitenoise, selected_whitenoise_filtered, selected_whitenoise_signal, shifted_signal, \
shifted_whitenoise
# this plots white_noise_signal_shift
def plt_white_noise_signal_shift(n: int, N: int, num_ar: int, shift, operations, size=(10, 7.5)):
whitenoise, whitenoise_filtered, whitenoise_signal, shifted_signal, shifted_whitenoise \
= white_noise_signal_shift(n, N, num_ar, shift, operations)
fig = plt.figure(figsize=size)
ax1 = plt.subplot2grid((3, 2), (0, 0), rowspan=1, colspan=2)
ax2 = plt.subplot2grid((3, 2), (1, 0), rowspan=1, colspan=1)
ax3 = plt.subplot2grid((3, 2), (2, 0), rowspan=1, colspan=1)
ax4 = plt.subplot2grid((3, 2), (1, 1), rowspan=1, colspan=1, sharey=ax2)
ax5 = plt.subplot2grid((3, 2), (2, 1), rowspan=1, colspan=1, sharey=ax3)
ax1.set_title('1) Original white noise')
ax2.set_title('2) Filtered original white noise'), ax2.set_ylabel('Log(P)'), ax2.set_xlabel('Log(f)')
ax3.set_title('3) Original signal')
ax4.set_title('5) White noise from the shifted signal'), ax4.set_ylabel('Log(P)'), ax4.set_xlabel('Log(f)')
ax5.set_title('4) Shifted signal')
# plotting the whitenoise
ax1.plot(whitenoise)
# plotting white the original data
ax2.loglog(whitenoise_filtered)
ax3.plot(whitenoise_signal)
# plotting the shifted data
ax4.loglog(shifted_whitenoise)
ax5.plot(shifted_signal)
plt.tight_layout()
plt.show()
rnd.seed(50)
# to run the script
plt_white_noise_signal_shift(100, 50, 50, 0, 0)