Как я могу заполнить N-мерный массив в HDF5 из 1D источника?

StackOverflow https://stackoverflow.com//questions/20007123

  •  20-12-2019
  •  | 
  •  

Вопрос

У меня есть массив с несколькими размерами (x, y, каналами, z, шаги времени). Тем не менее, необработанные данные хранятся в виде TIFF в качестве одной стеки (X, Y, каналов), с Z * рамами временных шагов.

Наконец, функция подушки. GTEDDATA () Функция возвращает 1D, подобный массивому объекту, который должен быть изменен.

Какой лучший способ прочитать это в HDF5, если набор данных слишком большой, чтобы вписаться в память? Можно ли изменить массив, как только он был записан в HDF5 или писать 1D данные таким образом, чтобы он автоматически заполняет массив (т.е. пишет с x, варьируясь быстрыми, y второй быстрый и т. Д.) <Сильное> Обновление : что-то вроде numpy.ndarray.flat < / a> Был бы идеал.

Вот то, что я пробовал до сих пор (img - pill.image, dset - это набор данных H5PY):

1) Чтение отдельных кадров. Этот метод слишком медленно, поскольку он занимает ~ 20 минут на 300 МБ в 1000 кадрах. Большую часть времени проводится в DSET []= вызов.

for i in range(0, img_layers):
  img.seek(i)
  a = numpy.array(img.getdata(), dtype=dtype) # a.shape = (sx * sz * channels,)
  a.resize(sx, sy, channels)
  z = i % sz
  frame = i // sz
  dset[..., z, frame] = a
.

2) <Сильные> Неполные: чтение в кусках. Это намного быстрее (2 минуты для одного и того же набора данных), но я получил только это работать для 4D-изображения (SX, SY, каналов, шагов времени) и нуждается в дополнительных измерении для Z-ломтиков:

chunk_bits = 256 * 1000**2 # 256MB
frame_bits = depth_bits[dtype] * sx * sy * channels
chunk_frames = chunk_bits // frame_bits
a = numpy.zeros((sx, sy, channels, chunk_frames), dtype=dtype)
for i in range(0, layers):
  img.seek(i)
  temp = numpy.array(img.getdata(), dtype=dtype)
  temp.resize(sx, sy, channels)
  a[..., i % chunk_frames] = temp
  if (i + 1) % chunk_frames == 0 or i == (layers - 1):
    chunk = i // chunk_frames
    dset[..., chunk * chunk_frames : i + 1] = a[..., : i % chunk_frames + 1
.

Это было полезно?

Решение

Вариант 1 был правильным ответом.Тем не менее, это имеет большую разницу, размерность изменений варьируется быстрее всего:

<Сильные> ~ 15 минут:

for i in range(0, img_layers):
  img.seek(i)
  a = numpy.array(img.getdata(), dtype=dtype)
  a.resize(sx, sy, channels)
  z = i % sz
  frame = i // sz
  dset[..., z, frame] = a # Majority of time in this call
.

<Сильные> ~ 3 минуты:

for i in range(0, img_layers):
  img.seek(i)
  a = numpy.array(img.getdata(), dtype=dtype) # Majority of time in this call
  a.resize(sx, sy, channels)
  z = i % sz
  frame = i // sz
  dset[frame, z, ...] = a
.

Чтобы быстро прочитать эти данные, самый быстрый разной индекс должен быть последним, не первый.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top