spatialimages

A simple spatial image class

The image class maintains the association between a 3D (or greater) array, and an affine transform that maps voxel coordinates to some world space. It also has a header - some standard set of meta-data that is specific to the image format, and extra - a dictionary container for any other metadata.

It has attributes:

  • extra

methods:

  • .get_fdata()

  • .to_filename(fname) - writes data to filename(s) derived from fname, where the derivation may differ between formats.

  • to_file_map() - save image to files with which the image is already associated.

properties:

  • shape

  • affine

  • header

  • dataobj

classmethods:

  • from_filename(fname) - make instance by loading from filename

  • from_file_map(fmap) - make instance from file map

  • instance_to_filename(img, fname) - save img instance to filename fname.

You cannot slice an image, and trying to slice an image generates an informative TypeError.

There are several ways of writing data.

There is the usual way, which is the default:

img.to_filename(fname)

and that is, to take the data encapsulated by the image and cast it to the datatype the header expects, setting any available header scaling into the header to help the data match.

You can load the data into an image from file with:

img.from_filename(fname)

The image stores its associated files in its file_map attribute. In order to just save an image, for which you know there is an associated filename, or other storage, you can do:

img.to_file_map()

You can get the data out again with:

img.get_fdata()

Less commonly, for some image types that support it, you might want to fetch out the unscaled array via the object containing the data:

unscaled_data = img.dataoobj.get_unscaled()

Analyze-type images (including nifti) support this, but others may not (MINC, for example).

Sometimes you might to avoid any loss of precision by making the data type the same as the input:

hdr = img.header
hdr.set_data_dtype(data.dtype)
img.to_filename(fname)

Files interface

The image has an attribute file_map. This is a mapping, that has keys corresponding to the file types that an image needs for storage. For example, the Analyze data format needs an image and a header file type for storage:

>>> import numpy as np
>>> import nibabel as nib
>>> data = np.arange(24, dtype='f4').reshape((2,3,4))
>>> img = nib.AnalyzeImage(data, np.eye(4))
>>> sorted(img.file_map)
['header', 'image']

The values of file_map are not in fact files but objects with attributes filename, fileobj and pos.

The reason for this interface, is that the contents of files has to contain enough information so that an existing image instance can save itself back to the files pointed to in file_map. When a file holder holds active file-like objects, then these may be affected by the initial file read; in this case, the contains file-like objects need to carry the position at which a write (with to_file_map) should place the data. The file_map contents should therefore be such, that this will work:

>>> # write an image to files
>>> from io import BytesIO
>>> import nibabel as nib
>>> file_map = nib.AnalyzeImage.make_file_map()
>>> file_map['image'].fileobj = BytesIO()
>>> file_map['header'].fileobj = BytesIO()
>>> img = nib.AnalyzeImage(data, np.eye(4))
>>> img.file_map = file_map
>>> img.to_file_map()
>>> # read it back again from the written files
>>> img2 = nib.AnalyzeImage.from_file_map(file_map)
>>> np.all(img2.get_fdata(dtype=np.float32) == data)
True
>>> # write, read it again
>>> img2.to_file_map()
>>> img3 = nib.AnalyzeImage.from_file_map(file_map)
>>> np.all(img3.get_fdata(dtype=np.float32) == data)
True

HasDtype(*args, **kwargs)

HeaderDataError

Class to indicate error in getting or setting header data

HeaderTypeError

Class to indicate error in parameters into header functions

ImageDataError

SpatialFirstSlicer(img)

Slicing interface that returns a new image with an updated affine

SpatialHeader(data_dtype, shape, zooms)

Template class to implement header protocol

SpatialImage(dataobj, affine[, header, ...])

Template class for volumetric (3D/4D) images

SpatialProtocol(*args, **kwargs)

supported_np_types(obj)

Numpy data types that instance obj supports

HasDtype

class nibabel.spatialimages.HasDtype(*args, **kwargs)

Bases: Protocol

__init__(*args, **kwargs)
get_data_dtype() dtype
set_data_dtype(dtype: npt.DTypeLike) None

HeaderDataError

class nibabel.spatialimages.HeaderDataError

Bases: Exception

Class to indicate error in getting or setting header data

__init__(*args, **kwargs)

HeaderTypeError

class nibabel.spatialimages.HeaderTypeError

Bases: Exception

Class to indicate error in parameters into header functions

__init__(*args, **kwargs)

ImageDataError

class nibabel.spatialimages.ImageDataError

Bases: Exception

__init__(*args, **kwargs)

SpatialFirstSlicer

class nibabel.spatialimages.SpatialFirstSlicer(img: SpatialImgT)

Bases: Generic[SpatialImgT]

Slicing interface that returns a new image with an updated affine

Checks that an image’s first three axes are spatial

__init__(img: SpatialImgT)
check_slicing(slicer: object, return_spatial: bool = False) tuple[slice | int | None, ...]

Canonicalize slicers and check for scalar indices in spatial dims

Parameters:
slicerobject

something that can be used to slice an array as in arr[sliceobj]

return_spatialbool

return only slices along spatial dimensions (x, y, z)

Returns:
slicerobject

Validated slicer object that will slice image’s dataobj without collapsing spatial dimensions

img: SpatialImgT
slice_affine(slicer: object) ndarray

Retrieve affine for current image, if sliced by a given index

Applies scaling if down-sampling is applied, and adjusts the intercept to account for any cropping.

Parameters:
slicerobject

something that can be used to slice an array as in arr[sliceobj]

Returns:
affine(4,4) ndarray

Affine with updated scale and intercept

SpatialHeader

class nibabel.spatialimages.SpatialHeader(data_dtype: npt.DTypeLike = <class 'numpy.float32'>, shape: Sequence[int] = (0, ), zooms: Sequence[float] | None = None)

Bases: FileBasedHeader, SpatialProtocol

Template class to implement header protocol

__init__(data_dtype: npt.DTypeLike = <class 'numpy.float32'>, shape: Sequence[int] = (0, ), zooms: Sequence[float] | None = None)
copy() SpatialHdrT

Copy object to independent representation

The copy should not be affected by any changes to the original object.

data_from_fileobj(fileobj: io.IOBase) np.ndarray

Read binary image data from fileobj

data_layout: Literal['F', 'C'] = 'F'
data_to_fileobj(data: npt.ArrayLike, fileobj: io.IOBase, rescale: bool = True)

Write array data data as binary to fileobj

Parameters:
dataarray-like

data to write

fileobjfile-like object

file-like object implementing ‘write’

rescale{True, False}, optional

Whether to try and rescale data to match output dtype specified by header. For this minimal header, rescale has no effect

default_x_flip: bool = True
classmethod from_header(header: SpatialProtocol | FileBasedHeader | Mapping | None = None) SpatialHdrT
get_base_affine() ndarray
get_best_affine() ndarray
get_data_dtype() dtype
get_data_shape() tuple[int, ...]
get_zooms() tuple[float, ...]
set_data_dtype(dtype: npt.DTypeLike) None
set_data_shape(shape: Sequence[int]) None
set_zooms(zooms: Sequence[float]) None

SpatialImage

class nibabel.spatialimages.SpatialImage(dataobj: ArrayLike, affine: np.ndarray | None, header: FileBasedHeader | ty.Mapping | None = None, extra: ty.Mapping | None = None, file_map: FileMap | None = None)

Bases: DataobjImage

Template class for volumetric (3D/4D) images

Initialize image

The image is a combination of (array-like, affine matrix, header), with optional metadata in extra, and filename / file-like objects contained in the file_map mapping.

Parameters:
dataobjobject

Object containing image data. It should be some object that returns an array from np.asanyarray. It should have a shape attribute or property

affineNone or (4,4) array-like

homogeneous affine giving relationship between voxel coordinates and world coordinates. Affine can also be None. In this case, obj.affine also returns None, and the affine as written to disk will depend on the file format.

headerNone or mapping or header instance, optional

metadata for this image format

extraNone or mapping, optional

metadata to associate with image that cannot be stored in the metadata of this image type

file_mapmapping, optional

mapping giving file information for this image format

__init__(dataobj: ArrayLike, affine: np.ndarray | None, header: FileBasedHeader | ty.Mapping | None = None, extra: ty.Mapping | None = None, file_map: FileMap | None = None)

Initialize image

The image is a combination of (array-like, affine matrix, header), with optional metadata in extra, and filename / file-like objects contained in the file_map mapping.

Parameters:
dataobjobject

Object containing image data. It should be some object that returns an array from np.asanyarray. It should have a shape attribute or property

affineNone or (4,4) array-like

homogeneous affine giving relationship between voxel coordinates and world coordinates. Affine can also be None. In this case, obj.affine also returns None, and the affine as written to disk will depend on the file format.

headerNone or mapping or header instance, optional

metadata for this image format

extraNone or mapping, optional

metadata to associate with image that cannot be stored in the metadata of this image type

file_mapmapping, optional

mapping giving file information for this image format

ImageSlicer

alias of SpatialFirstSlicer

property affine
as_reoriented(ornt: Sequence[Sequence[int]]) SpatialImgT

Apply an orientation change and return a new image

If ornt is identity transform, return the original image, unchanged

Parameters:
ornt(n,2) orientation array

orientation transform. ornt[N,1]` is flip of axis N of the array implied by `shape`, where 1 means no flip and -1 means flip.  For example, if ``N==0 and ornt[0,1] == -1, and there’s an array arr of shape shape, the flip would correspond to the effect of np.flipud(arr). ornt[:,0] is the transpose that needs to be done to the implied array, as in arr.transpose(ornt[:,0])

Notes

Subclasses should override this if they have additional requirements when re-orienting an image.

classmethod from_image(img: SpatialImage | FileBasedImage) SpatialImgT

Class method to create new instance of own class from img

Parameters:
imgspatialimage instance

In fact, an object with the API of spatialimage - specifically dataobj, affine, header and extra.

Returns:
cimgspatialimage instance

Image, of our own class

get_data_dtype() dtype
header_class

alias of SpatialHeader

orthoview() OrthoSlicer3D

Plot the image using OrthoSlicer3D

Returns:
viewerinstance of OrthoSlicer3D

The viewer.

Notes

This requires matplotlib. If a non-interactive backend is used, consider using viewer.show() (equivalently plt.show()) to show the figure.

set_data_dtype(dtype: npt.DTypeLike) None
property slicer: SpatialFirstSlicer[SpatialImgT]

Slicer object that returns cropped and subsampled images

The image is resliced in the current orientation; no rotation or resampling is performed, and no attempt is made to filter the image to avoid aliasing.

The affine matrix is updated with the new intercept (and scales, if down-sampling is used), so that all values are found at the same RAS locations.

Slicing may include non-spatial dimensions. However, this method does not currently adjust the repetition time in the image header.

update_header() None

Harmonize header with image data and affine

>>> data = np.zeros((2,3,4))
>>> affine = np.diag([1.0,2.0,3.0,1.0])
>>> img = SpatialImage(data, affine)
>>> img.shape == (2, 3, 4)
True
>>> img.update_header()
>>> img.header.get_data_shape() == (2, 3, 4)
True
>>> img.header.get_zooms()
(1.0, 2.0, 3.0)

SpatialProtocol

class nibabel.spatialimages.SpatialProtocol(*args, **kwargs)

Bases: Protocol

__init__(*args, **kwargs)
get_data_dtype() dtype
get_data_shape() tuple[int, ...]
get_zooms() tuple[float, ...]

supported_np_types

nibabel.spatialimages.supported_np_types(obj: HasDtype) set[type[generic]]

Numpy data types that instance obj supports

Parameters:
objobject

Object implementing get_data_dtype and set_data_dtype. The object should raise HeaderDataError for setting unsupported dtypes. The object will likely be a header or a SpatialImage

Returns:
np_typesset

set of numpy types that obj supports