.. _biap7: ############################### BIAP7 - Loading multiple images ############################### :Author: Matthew Brett :Status: Draft :Type: Standards :Created: 2015-07-18 ********** Background ********** Some formats store images with different shapes in the same file ================================================================ The ECAT file format can contain more than one type of image in a single image file. ECAT can store many *frames* in a single image file. Each frame has its own *subheader*. The subheader specifies the 3D image size; each frame can therefore have a different image size. We currently raise an error if you try and load an ECAT file where the frames do not have the same 3D dimensions. It would be better if we could allow loading multiple images with different image dimensions, from a single ECAT file. `Vista data format`_ and `Lipsia format`_ are other formats that allow saving multiple images with different image dimensions in the same file. We don't currently support Lipsia or Vista formats and it is not clear how we would do that with the current ``load`` API. We have had some discussion about saving multiple images into a single HDF5 file - see https://github.com/nipy/nibabel/pull/215#issuecomment-122357444 It can be useful to load 4D images as multiple 3D images ======================================================== We sometimes want to load a 4D image as multiple 3D images. When we are doing motion correction, we often want to split up a 4D image into separate 3D images. Motion estimation results in different affines for each volume in the 4D time series. At the moment we have no API for returning these affines with a 4D image. One way of doing that is to load the 4D image and affines as a sequence of 3D images, each with their own affine. We currently have a proposal open for a JSON header extension that can store these 4D affines for a 4D NIfTI file. SPM saves the affines in an associated ``.mat`` file, with one affine per volume in the 4D image. ******* Options ******* ************************************************************ Return an image sequence from ``load`` for some file formats ************************************************************ We don't currently load ECAT files from the top-level ``nibabel.load`` function. We do have ``nibabel.ecat.load``, which raises an error for an ECAT file having frames with different image dimensions. We could therefore choose to return a sequence of images from ``nibabel.load`` on an ECAT file, with one element per frame in the ECAT file. Most ECAT images are 4D images, in the sense that the frames in the file do all have the same image dimensions and data type, so this might be cumbersome as a default. We would have to work out how to deal with ``nibabel.ecat.load``. The same principles apply to the Lipsia / Vista formats, except we have no backward-compatibility problems, and it seems to be more common for these formats to mix image types in a single file. *************************************** Add a ``load_multi`` top-level function *************************************** ``nibabel.load_multi`` always returns an image sequence. ``nibabel.load`` always returns a single image. ``nibabel.load`` on ECAT (etc) files could first do ``load_multi``, then check the resulting image dimensions, raising an error if incompatible, concatenating otherwise. ``load_multi`` on current formats like NIfTI could return one image per volume, where each volume might have its own affine, as loaded from the JSON header extension or the SPM ``.mat`` file. .. _Lipsia format: http://static.cbs.mpg.de/lipsia/START/index3.html .. _Vista data format: http://www.cs.ubc.ca/labs/lci/vista/file.html .. vim:ft=rst *************************************** Next steps: *************************************** * Make sure there are use-cases where you could wish to call `load` vs. `load_multi` on the same image (perhaps a Nifti image with different affines for each volume) * Investigate AFNI file formats as a use-case for this. * Check the `nilearn` codebase, see if `iter_img` and `slice_img` functions might offer a post-`load` alternative. Also check if those functions could be deprecated in favor of slicing / iterating on `dataobj` * Create a new issue to implement getting an iterator on `dataobj`?