¿Cómo llenamo una matriz N-dimensional en HDF5 de una fuente 1D?
Pregunta
Tengo una matriz con múltiples dimensiones (x, y, canales, z, pasos de tiempo). Sin embargo, los datos en bruto se almacenan en una imagen TIFF como una sola pila de (x, y, canales), con marcos Z * pasos de tiempo.
Finalmente, la función Image.GetData () devuelve un objeto similar a una matriz 1D que necesita ser remodelada.
¿Cuál es la mejor manera de leer esto en HDF5 si el conjunto de datos es demasiado grande para caber en la memoria? ¿Es posible remodelar la matriz una vez que se haya escrito en HDF5, o para escribir datos 1D de una manera que complete automáticamente una matriz (es decir, escribe con x variable más rápido, y segundo, etc.) actualización : algo como numpy.ndarray.flat < / a> sería ideal.
Aquí está lo que he intentado hasta ahora (IMG es Pil.Image, Dset es un conjunto de datos H5PY):
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
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
Solución
La opción 1 fue la respuesta correcta.Sin embargo, hace una gran diferencia en la que la dimensión varía más rápido:
~ 15 minutos:
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 minutos:
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
Para leer estos datos rápidamente, el índice variable más rápido debe ser el último, no primero.