我对疾病问题进行建模,其中2D景观中的每个个体都具有由(径向基)核函数描述的传递性。我的目标是将内核与人口密度进行卷积,以便输出捕获整个环境中的传输风险。
我使用NumPy的2D FFT和反FFT函数执行卷积。但是,这会强制结果中的周期性/包裹边界条件,这不适合我的模型。有没有办法在原始固定边界的范围内进行卷积?
import numpy as np
import random
from math import *
import matplotlib.pyplot as plt
''' Landscape parameters '''
L = 10.
nx = 100
dx = L/nx
hs = .5 * dx # half-step
ulist = np.linspace(hs, L-hs, nx)
''' Radial Basis Function Kernel '''
alpha = 1.
i, j = ulist.reshape(nx,1), ulist.reshape(1,nx)
r = np.minimum(i-ulist[0], L-i+ulist[0])**2 + np.minimum(j-ulist[0], L-j+ulist[0])**2
rbf = sqrt(1 / (2 * alpha ** 2))
ker = np.exp(-(rbf * r) ** 2)
ker = ker/np.sum(ker)
''' Population Density '''
ido = np.random.randint(nx, size=(1000,2)).astype(np.int)
og = np.zeros((nx,nx))
np.add.at(og, (ido[:,0], ido[:,1]), 1)
''' Convolution via FFT and inverse-FFT '''
v1 = np.fft.fft2(ker)
v2 = np.fft.fft2(og)
v0 = np.fft.ifft2(v1*v2)
dd = np.abs(v0)
plt.plot(ido[:,1], ido[:,0], 'ko', alpha=.5)
plt.imshow(dd, origin='origin')
plt.show()
答案 0 :(得分:2)
为了做你想做的事,你需要用{0}来填充og
,然后相应地展开ker
(因为它已经周期性地移动了,你只需要将它扩展到更适合的大小og
)。
填充og
(300x300):
原始ker
(100x100):
扩展ker
(300x300):
代码:
pad = 100
og = np.pad(og, pad, mode='constant')
new_ker = np.zeros_like(og)
new_ker[:nx//2,:nx//2] = ker[:nx//2,:nx//2]
new_ker[:nx//2,-nx//2:] = ker[:nx//2,-nx//2:]
new_ker[-nx//2:,:nx//2] = ker[-nx//2:,:nx//2]
new_ker[-nx//2:,-nx//2:] = ker[-nx//2:,-nx//2:]
ker = new_ker
# doesn't change
v1 = np.fft.fft2(ker)
v2 = np.fft.fft2(og)
v0 = np.fft.ifft2(v1*v2)
# unpadding the result
v0 = v0[pad:-pad,pad:-pad]
(对于凌乱的扩展,很抱歉,你可以在生成内核时直接进行扩展。我只想分离扩展部分。)
如果您不介意使用scipy
,它可以为您完成所有这些(包括边界条件的其他变体)。有关更多选项,请参阅fftconvolve
或convolve2d
。请注意,不必须预先滚动内核才能使用这些功能(也就是说,最大值应位于中心,而不是在角落中)。示例代码(产生与上面手动填充相同的结果):
# unroll the kernel (again, can be done directly when generating `ker`)
ker = np.roll(ker, 50, 0)
ker = np.roll(ker, 50, 1)
from scipy.signal import fftconvolve
dd = fftconvolve(og, ker, mode='same')
答案 1 :(得分:2)
每当您使用基于fft
的方法时,您总是会根据定义在问题中引入周期性问题。
如果您不想要这个,首先应该在计算级别之前在数学建模级别定义您想要的内容。
请记住一些技巧,根据我的经验,在许多情况下非常有用:
- 将您的问题嵌入更大的2d空间以减少周期性影响。换句话说,尽可能地推动周期性边界以模拟“自由空间”。情况。
- 改为使用离散余弦变换。余弦变换具有模拟边界条件的效果。它的工作原理就像在每个边界之外都有镜像反射的数据。在某些问题中,这用于模拟反射边界条件。