Source code for nipy.core.image.image_list

from __future__ import absolute_import
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
import warnings

import numpy as np

from .image import Image, iter_axis, is_image
from ..reference.coordinate_map import (drop_io_dim, io_axis_indices, AxisError)

from ...externals.six import Iterator


[docs]class ImageList(Iterator): ''' Class to contain ND image as list of (N-1)D images '''
[docs] def __init__(self, images=None): """ An implementation of a list of images. Parameters ---------- images : iterable an iterable object whose items are meant to be images; this is checked by asserting that each has a `coordmap` attribute and a ``get_data`` method. Note that Image objects are not iterable by default; use the ``from_image`` classmethod or ``iter_axis`` function to convert images to image lists - see examples below for the latter. Examples -------- >>> from nipy.testing import funcfile >>> from nipy.core.api import Image, ImageList, iter_axis >>> from nipy.io.api import load_image >>> funcim = load_image(funcfile) >>> iterable_img = iter_axis(funcim, 't') >>> ilist = ImageList(iterable_img) >>> sublist = ilist[2:5] Slicing an ImageList returns a new ImageList >>> isinstance(sublist, ImageList) True Indexing an ImageList returns a new Image >>> newimg = ilist[2] >>> isinstance(newimg, Image) True >>> isinstance(newimg, ImageList) False >>> np.asarray(sublist).shape (3, 17, 21, 3) >>> newimg.get_data().shape (17, 21, 3) """ if images is None: self.list = [] return images = list(images) if not all(is_image(im) for im in images): raise ValueError("Expecting each element of images to have " "the Image API") self.list = images
[docs] @classmethod def from_image(klass, image, axis=None, dropout=True): """ Create an image list from an `image` by slicing over `axis` Parameters ---------- image : object object with ``coordmap`` attribute axis : str or int axis of `image` that should become the axis indexed by the image list. dropout : bool, optional When taking slices from an image, we will leave an output dimension to the coordmap that has no corresponding input dimension. If `dropout` is True, drop this output dimension. Returns ------- ilist : ``ImageList`` instance """ if axis is None: raise ValueError('Must specify image axis') # Get corresponding input, output dimension indices in_ax, out_ax = io_axis_indices(image.coordmap, axis) if in_ax is None: raise AxisError('No correspnding input dimension for %s' % axis) dropout = dropout and out_ax is not None if dropout: out_ax_name = image.reference.coord_names[out_ax] imlist = [] for img in iter_axis(image, in_ax): if dropout: cmap = drop_io_dim(img.coordmap, out_ax_name) img = Image(img.get_data(), cmap, img.metadata) imlist.append(img) return klass(imlist)
def __setitem__(self, index, value): """ self.list[index] = value """ self.list[index] = value def __len__(self): """ Length of image list """ return len(self.list) def __getitem__(self, index): """ self.list[index] """ # Integer slices return elements if type(index) is type(1): return self.list[index] # List etc slicing return new instances of self.__class__ return self.__class__(images=self.list[index])
[docs] def get_list_data(self, axis=None): """Return data in ndarray with list dimension at position `axis` Parameters ---------- axis : int `axis` specifies which axis of the output will take the role of the list dimension. For example, 0 will put the list dimension in the first axis of the result. Returns ------- data : ndarray data in image list as array, with data across elements of the list concetenated at dimension `axis` of the array. Examples -------- >>> from nipy.testing import funcfile >>> from nipy.io.api import load_image >>> funcim = load_image(funcfile) >>> ilist = ImageList.from_image(funcim, axis='t') >>> ilist.get_list_data(axis=0).shape (20, 17, 21, 3) """ if axis is None: raise ValueError('Must specify which axis of the output will take ' 'the role of the list dimension, eg 0 will put ' 'the list dimension in the first axis of the ' 'result') img_shape = self.list[0].shape ilen = len(self.list) out_dim = len(img_shape) + 1 if axis >= out_dim or axis < -out_dim: raise ValueError('I have only %d axes position, but axis %d asked ' 'for' % (out_dim -1, axis)) # tmp_shape is the shape of the output if axis is 0 tmp_shape = (ilen,) + img_shape v = np.empty(tmp_shape) # first put the data in an array, with list dimension in the first axis for i, im in enumerate(self.list): v[i] = im.get_data() # get_data method of an image has no axis # then roll (and rock?) the axis to have axis in the right place if axis < 0: axis += out_dim res = np.rollaxis(v, 0, axis + 1) # Check we got the expected shape target_shape = img_shape[0:axis] + (ilen,) + img_shape[axis:] if target_shape != res.shape: raise ValueError('We were not expecting this shape') return res
def __array__(self): """Return data in ndarray. Called through numpy.array. Examples -------- >>> from nipy.testing import funcfile >>> from nipy.io.api import load_image >>> funcim = load_image(funcfile) >>> ilist = ImageList.from_image(funcim, axis='t') >>> np.asarray(ilist).shape (20, 17, 21, 3) """ """Return data as a numpy array.""" warnings.warn('Please use get_list_data() instead - default ' 'conversion to array will be deprecated', DeprecationWarning, stacklevel=2) return self.get_list_data(axis=0) def __iter__(self): self._iter = iter(self.list) return self def __next__(self): return next(self._iter)