Деконволюция отклика системы в Python/Matlab

#python #matlab #signal-processing #convolution #deconvolution

Вопрос:

У меня было два набора данных: функция вывода системы (временной ряд длиной 1292 записи) и функция передачи (аналогичная гауссовой с длиной 681 запись). Я хотел бы вычислить входную функцию(неизвестную) с помощью деконволюции.

Я попытался вычислить БПФ для каждой функции, а затем обратную величину деления двух БПФ:

Cin = F^-1 [F(Cout)]/[F(E)]

однако БПФ передаточной функции, по-видимому, везде равна нулю, и результирующий восстановленный сигнал имеет много шума. Я также попробовал деконволюцию Винера, но еще раз, если я вычислю свертку восстановленного сигнала с помощью передаточной функции, я не получу выходную функцию.

  • Для сигналов, которые я использую, какой метод наиболее подходит? (БПФ, сверток СциПи, Сосиска)
  • Нужно ли мне «обнулять» передаточную функцию, чтобы она соответствовала длине выходной функции?
  • Поскольку процесс деконволюции восприимчив к шуму, нужно ли фильтровать сигналы (до/после)?
  • есть подобный код в matlab или python, на который я мог бы сослаться?

Здесь вывод моего кода с помощью метода Винера (вывод синим цветом, передача красным, восстановленный ввод зеленым цветом и свертка восстановленного ввода и передачи (фиолетовый):

вывод по методу Винера

и код для деконволюции Винера:

 #import data
data = pandas.read_csv("data/hetre20mod.csv")
x = data.Time

#normalize data
norm = (data.CO-data.CO.min()) / (data.CO.max()-data.CO.min())

# transfer function
length = 681
pe = 27
ttau = 203
ao = rtdpy.AD_oo(tau=ttau, peclet=pe, dt=1, time_end=length)
rtd = ao.exitage

#zero pad transfer function
kernel = np.hstack((rtd, np.zeros(len(norm) - len(rtd))))

#wiener deconvolution
lambd = 0.00035
H = np.fft.fft(kernel)
deconv = np.fft.ifft(np.fft.ifft(np.fft.fft(norm)*np.conj(H)/(H*np.conj(H)   lambd**2)))


recovered = np.convolve(deconv, kernel, mode='same') 

fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(4, 4))
ax[0][0].plot(x, norm, 'b', label="experimental", lw=3)
ax[0][1].plot(x, kernel, 'r', label="transfer", lw=3)
ax[1][0].plot(x, deconv, 'g', label="treated", lw=3)
ax[1][1].plot(x, recovered, 'm', label="both", lw=3)
ax[1][1].plot(x, norm, 'b',label="both", lw=3)
plt.show()
 

Комментарии:

1. Помните, что все, что вы делаете с помощью БПФ, подразумевает предположение о периодичности сигнала. Я бы обнулил сигнал, чтобы удвоить его размер, чтобы избежать каких-либо последствий этого. И да, затем вам нужно обнулить передаточную функцию. Пожалуйста, опубликуйте код, который вы использовали, чтобы мы могли указать, в чем проблема.

2. Я просто добавляю код для деконволюции Винера. Значит, мне нужно обнулить оба сигнала?

3. Почему вы подаете np.fft.ifft заявление дважды?

4. я просто меняю эту строку на: deconv = np.real(np.fft.ifft(np.fft.fft(norm)*np.conj(H)/(H*np.conj(H) lambd**2))) и в проверке я изменил режим свертки на полный.

5. Помогло ли это? Ваш результат ближе к тому, что вы ожидаете сейчас?