一個明顯的改進是使用廣播來評估你的強度功能在「疏」網,而不是一個完整的meshgrid
,如:
X, Y, Z = np.meshgrid(x, y, z, sparse=True)
這由約4倍的因子來減小運行時我機:
%timeit make_spot_3d(1., 1., 0, 0, 0)
1 loops, best of 3: 1.56 s per loop
%timeit make_spot_3d_ogrid(1., 1., 0, 0, 0)
1 loops, best of 3: 359 ms per loop
你可以擺脫通過在位置,利差和亮度矢量化計算參與列表理解的開銷,例如:
def make_spots(bright, spread, x0, y0, z0):
# Create x and y indices
x = np.linspace(-50, 50, 200)
y = np.linspace(-50, 50, 200)
z = np.linspace(-50, 50, 200)
# this will broadcast out to an (nblobs, ny, nx, nz) array
dx = x[None, None, :, None] - x0[:, None, None, None]
dy = y[None, :, None, None] - y0[:, None, None, None]
dz = z[None, None, None, :] - z0[:, None, None, None]
spread = spread[:, None, None, None]
bright = bright[:, None, None, None]
# we can save time by performing the exponentiation over 2D arrays
# before broadcasting out to 4D, since exp(a + b) == exp(a) * exp(b)
s2 = spread * spread
a = np.exp(-(dx * dx)/s2)
b = np.exp(-(dy * dy)/s2)
c = np.exp(-(dz * dz)/s2)
intensity = bright * a * b * c
return intensity.astype(np.uint16)
其中bright
,spread
,x0
,y0
和z0
是1D向量。這將生成一個(nblobs, ny, nx, nz)
數組,然後您可以總結第一個軸。根據您生成的blob數量以及您對它們進行評估的網格大小,創建此中間數組可能會在內存方面變得非常昂貴。
另一種選擇是初始化單個(ny, nx, nz)
輸出陣列,並計算就地的總和:
def sum_spots_inplace(bright, spread, x0, y0, z0):
# Create x and y indices
x = np.linspace(-50, 50, 200)
y = np.linspace(-50, 50, 200)
z = np.linspace(-50, 50, 200)
dx = x[None, None, :, None] - x0[:, None, None, None]
dy = y[None, :, None, None] - y0[:, None, None, None]
dz = z[None, None, None, :] - z0[:, None, None, None]
spread = spread[:, None, None, None]
bright = bright[:, None, None, None]
s2 = spread * spread
a = np.exp(-(dx * dx)/s2)
b = np.exp(-(dy * dy)/s2)
c = np.exp(-(dz * dz)/s2)
out = np.zeros((200, 200, 200), dtype=np.uint16)
for ii in xrange(bright.shape[0]):
out += bright[ii] * a[ii] * b[ii] * c[ii]
return out
這將需要較少的存儲器,但潛在的缺點是,它需要在Python循環。
爲了讓您的相對性能的一些想法:
def sum_spots_listcomp(bright, spread, x0, y0, z0):
return np.sum([make_spot_3d(bright[ii], spread[ii], x0[ii], y0[ii], z0[ii])
for ii in xrange(len(bright))], axis=0)
def sum_spots_vec(bright, spread, x0, y0, z0):
return make_spots(bright, spread, x0, y0, z0).sum(0)
# some fake data
bright = np.random.rand(10) * 100
spread = np.random.rand(10) * 100
x0 = (np.random.rand(10) - 0.5) * 50
y0 = (np.random.rand(10) - 0.5) * 50
z0 = (np.random.rand(10) - 0.5) * 50
%timeit sum_spots_listcomp(bright, spread, x0, y0, z0)
# 1 loops, best of 3: 16.6 s per loop
%timeit sum_spots_vec(bright, spread, x0, y0, z0)
# 1 loops, best of 3: 1.03 s per loop
%timeit sum_spots_inplace(bright, spread, x0, y0, z0)
# 1 loops, best of 3: 330 ms per loop
如何使一個blob archtype,然後縮放和移動它? (對於這一點,根據您需要的尺寸的精度和範圍,縮放可以更快,因此指定這可能會有所幫助)。 – tom10
是的,我看到如何縮放(* k)。爲了轉移,我恐怕找不到解決方案,因爲我需要將這些點均勻分佈在一個球體上(我使用的是來自http://bit.ly/1eNaH4z的代碼),因此預先計算了位置 –
我沒有想想你說什麼排除縮放。你能解釋更多嗎? – tom10