对于有限物体大小的衍射模拟器,我需要生成数组,这些数组是质心处高斯(或其他)2D 内核的数千个实例的总和,这些实例不会以任何可重复的方式落在网格点上。
下面是一个简单的例子,为了清楚起见,质心简单的六边形排列,以及一个更快的解析表达式,接近于这个特别简单的例子,但通常排列会更复杂甚至是随机的。
import numpy as np
import matplotlib.pyplot as plt
hw = 10
N = 250
twoNp1 = 2 * N + 1
ximg, yimg = np.mgrid[-hw:hw:twoNp1 * 1j, -hw:hw:twoNp1 * 1j]
a = np.sqrt(2)
sig1 = hw/3.
sig2 = a/5.
r3o2, twopi = np.sqrt(3) / 2, 2 * np.pi
vecs = a * np.array([[1, 0], [1/2, r3o2]])
nmax = int(2 * (ximg.max()/a)) # overfill overkill
i, j = [thing.flatten() for thing in np.mgrid[-nmax:nmax+1, -nmax:nmax+1]]
keep = np.abs(i + j) <= nmax
i, j = [thing[keep, None] for thing in (i, j)]
points = i * vecs[0] + j * vecs[1]
img = np.zeros_like(ximg)
for x, y in points:
img += np.exp(-((x-ximg)**2 + (y-yimg)**2) / (2 * sig2**2))
# actual gaussians
img *= np.exp(-((ximg)**2 + (yimg)**2) / (2 * sig1**2))
# sinusoidal pattern
k = (twopi / (a * r3o2)) * np.array([[1, 0], [0.5, r3o2], [0.5, -r3o2]])
# that's 0, 60, -60
# try -30, 30, 90
k = (twopi / (a * r3o2)) * np.array([[r3o2, -1/2], [r3o2, 1/2], [0, 1]])
phases = [kay[0] * ximg + kay[1] * yimg for kay in k]
amplitudes = [np.cos(phase) for phase in phases]
amplitude = (1.5 + sum(amplitudes))/4.5
amplitude *= np.exp(-((ximg)**2 + (yimg)**2) / (2 * sig1**2))
if False:
n = int((2 * hw / a)**2 + 0.5)
randoms = hw * (2 * np.random.random((n,2)) - 1)
rand = np.zeros_like(ximg)
for x, y in randoms:
rand += np.exp(-((x-ximg)**2 + (y-yimg)**2) / (2 * sig2**2))
rand *= np.exp(-((ximg)**2 + (yimg)**2) / (2 * sig1**2))
if True:
fig, (ax1, ax2) = plt.subplots(2, 1)
extent = [ximg.min(), ximg.max(), yimg.min(), yimg.max()]
one = ax1.imshow(img, origin='lower', extent=extent)
ax1.plot(ximg, hw * (img[N] - 1), '-r', linewidth=0.5)
ax1.set_title('"thousands" of Gaussians')
# fig.colorbar(one, ax=ax1)
two = ax2.imshow(amplitude, origin='lower', extent=extent)
ax2.plot(ximg, hw * (amplitude[N] - 1), '-r', linewidth=0.5)
ax2.set_title('sinusoidal approximation')
# fig.colorbar(two, ax=ax2)
plt.show()

