我有一个3D数组,我想用Dask将我的3D数组分块为每个轨迹周围具有特定窗口大小的轨迹块。迹线只是一个大小为(1,1,z)的向量。我可以使用以下numpy as_strided技巧来做到这一点:
import numpy as np
from numpy.lib.stride_tricks import as_strided
input_volume = np.linspace(1, 1000, 1000, dtype=int).reshape((10, 10, 10))
window_size = 5
x, y, z = input_volume.shape
# Create a view on the volume of sub-cubes window_size traces wide overlapping by 1 trace in each direction
half_w = (window_size - 1) // 2
padded = np.pad(input_volume[...], [(half_w, half_w), (half_w, half_w), (0, 0)], 'edge')
x_str, y_str, z_str = padded.strides
blocks = as_strided(padded, (x, y, window_size, window_size, z), (x_str, y_str, x_str, y_str, z_str))
averaged_volume = np.mean(blocks, (2, 3))
首先,我将3D多维数据集在x和y维度上填充半个窗口。我从每个块中获取平均轨迹,因此在这种情况下,(5,5,z)的块将减少为一条轨迹。然后,我得到的体积与在窗口尺寸上平均的体积相同。这有效地给了我3D阵列的“视图”,形状为(10,10,5,5,10)。
这有效,但是如果卷很大,则会将整个卷加载到内存中。
我一直在尝试通过分块数组来实现相同的目的,但是我无法正确设置深度和边界以给出相同的答案。我如何才能在dask中实现相同的目的,使其一次只将每个跟踪块加载到内存中,然后写回平均多维数据集?
编辑: 这是到目前为止我一直在尝试的简单代码,但是当它运行时,我得到一个IndexError:试图进行平均计算时,元组索引超出范围:
def average(block):
return np.mean(block, axis=(0, 1))
import dask.array as da
dask_volume = da.from_array(da.pad(input_volume, [(half_w, half_w), (half_w, half_w), (0, 0)], 'edge'), chunks=(window_size ,window_size, -1))
dask_overlapping = da.overlap.overlap(dask_volume, depth={0: window_size - 1, 1: window_size -1}, boundary={0: 'none', 1: 'none'})
dask_average = dask_overlapping.map_blocks(average, chunks=(1, 1, z)).compute()
谢谢
迈克