Ленивое чередование/переплетение массивов Dask

Мне нужно покадрово чередовать два больших набора данных HDF5, представляющих видеокадры из двух каналов микроскопического измерения. Я подумал, что Dask подойдет для этой работы и последующих процессов.

Два массива имеют одинаковую форму и тип данных. Основываясь на этой ссылке, я могу сделать это с помощью NumPy для массивов меньше памяти: Переплетение двух массивов numpy.

import numpy as np
# a numpy example of channel 1 data
ch1 = np.arange(1,5)[:,np.newaxis,np.newaxis]*np.ones((4,3,2))

# channel 2 has the same shape and dtype
ch2 = np.arange(10,50,10)[:,np.newaxis,np.newaxis]*np.ones((4,3,2))

# the interleaving starts with assigning a new array with douled size of the first dimension
ch1_2 = np.empty((2*ch1.shape[0],*ch1.shape[1:]), dtype=ch1.dtype)
# two assignments takes care of the interleaving 
ch1_2[0::2] = ch1
ch1_2[1::2] = ch2

К сожалению, это не относится к Dask.

import dask.array as da
da_ch1 = da.from_array(ch1)
da_ch2 = da.from_array(ch2)
da_ch1_2 = da.empty((2*da_ch1.shape[0],*da_ch1.shape[1:]), dtype=da_ch1.dtype)
da_ch1_2[0::2] = da_ch1
da_ch1_2[1::2] = da_ch2

Это завершается ошибкой: присвоение элемента с ‹классом 'slice'› не поддерживается.

Может ли кто-нибудь помочь мне с альтернативным подходом, совместимым с Dask? Любая помощь будет оценена по достоинству.


person msg    schedule 12.02.2021    source источник


Ответы (2)


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

import dask.array as da
from dask import delayed
import numpy as np

@delayed
def interleave(x1, x2):
    x1_2 = np.empty(ch1_2_shape, dtype=ch1.dtype)
    x1_2[0::2] = x1
    x1_2[1::2] = x2
    return x1_2

# a numpy example of channel 1 data
ch1 = np.arange(1,5)[:,np.newaxis,np.newaxis]*np.ones((4,3,2))

# channel 2 has the same shape and dtype
ch2 = np.arange(10,50,10)[:,np.newaxis,np.newaxis]*np.ones((4,3,2))

# Interleave using dask delayed
ch1_2_shape = (2*ch1.shape[0],*ch1.shape[1:])
ch1_2 = interleave(ch1, ch2)

# Convert to dask array if required
ch1_2 = da.from_delayed(interleave(ch1, ch2), ch1_2_shape, dtype=ch1.dtype)

ch1_2.compute()
person KRKirov    schedule 12.02.2021
comment
Спасибо, что обратили мое внимание на Даска с задержкой. Это кажется общеприменимым низкоуровневым решением. Между тем, я пришел к следующему: da_ch1_2 = da.rollaxis(da.stack((da_ch1,da_ch2)),axis=1).reshape((-1,*da_ch1.shape[1:])) Есть ли предпочтение между этими двумя подходами? - person msg; 12.02.2021
comment
Я думаю, вам придется поэкспериментировать со своей проблемой, чтобы увидеть, работает ли один лучше, чем другой. Ваше решение может обеспечить более последовательный и менее подробный способ выполнения ваших вычислений. Вы можете читать из файла прямо в массив dask и выполнять чередование и другие вычисления, не прибегая к пользовательским функциям. Я думаю, вы должны опубликовать свое решение в качестве ответа. Я бы сразу проголосовал. - person KRKirov; 12.02.2021

Это решение Dask Array высокого уровня для проблемы:

da_ch1_2=da.rollaxis(da.stack((da_ch1,da_ch2)),axis=1).reshape((-1,*da_ch1.shape[1:]))
person msg    schedule 12.02.2021