|
| 1 | +# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- |
| 2 | +# vi: set ft=python sts=4 ts=4 sw=4 et: |
| 3 | +### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## |
| 4 | +# |
| 5 | +# See COPYING file distributed along with the NiBabel package for the |
| 6 | +# copyright and license terms. |
| 7 | +# |
| 8 | +### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## |
| 9 | +"""Resampling utilities.""" |
| 10 | +from pathlib import Path |
| 11 | +import numpy as np |
| 12 | +import h5py |
| 13 | +import warnings |
| 14 | +from nibabel.loadsave import load as _nbload |
| 15 | +from nibabel import funcs as _nbfuncs |
| 16 | +from nibabel.nifti1 import intent_codes as INTENT_CODES |
| 17 | +from nibabel.cifti2 import Cifti2Image |
| 18 | +from scipy import ndimage as ndi |
| 19 | + |
| 20 | + |
| 21 | +def apply( |
| 22 | + transform, |
| 23 | + spatialimage, |
| 24 | + reference=None, |
| 25 | + order=3, |
| 26 | + mode="constant", |
| 27 | + cval=0.0, |
| 28 | + prefilter=True, |
| 29 | + output_dtype=None, |
| 30 | +): |
| 31 | + """ |
| 32 | + Apply a transformation to an image, resampling on the reference spatial object. |
| 33 | +
|
| 34 | + Parameters |
| 35 | + ---------- |
| 36 | + spatialimage : `spatialimage` |
| 37 | + The image object containing the data to be resampled in reference |
| 38 | + space |
| 39 | + reference : spatial object, optional |
| 40 | + The image, surface, or combination thereof containing the coordinates |
| 41 | + of samples that will be sampled. |
| 42 | + order : int, optional |
| 43 | + The order of the spline interpolation, default is 3. |
| 44 | + The order has to be in the range 0-5. |
| 45 | + mode : {'constant', 'reflect', 'nearest', 'mirror', 'wrap'}, optional |
| 46 | + Determines how the input image is extended when the resamplings overflows |
| 47 | + a border. Default is 'constant'. |
| 48 | + cval : float, optional |
| 49 | + Constant value for ``mode='constant'``. Default is 0.0. |
| 50 | + prefilter: bool, optional |
| 51 | + Determines if the image's data array is prefiltered with |
| 52 | + a spline filter before interpolation. The default is ``True``, |
| 53 | + which will create a temporary *float64* array of filtered values |
| 54 | + if *order > 1*. If setting this to ``False``, the output will be |
| 55 | + slightly blurred if *order > 1*, unless the input is prefiltered, |
| 56 | + i.e. it is the result of calling the spline filter on the original |
| 57 | + input. |
| 58 | + output_dtype: dtype specifier, optional |
| 59 | + The dtype of the returned array or image, if specified. |
| 60 | + If ``None``, the default behavior is to use the effective dtype of |
| 61 | + the input image. If slope and/or intercept are defined, the effective |
| 62 | + dtype is float64, otherwise it is equivalent to the input image's |
| 63 | + ``get_data_dtype()`` (on-disk type). |
| 64 | + If ``reference`` is defined, then the return value is an image, with |
| 65 | + a data array of the effective dtype but with the on-disk dtype set to |
| 66 | + the input image's on-disk dtype. |
| 67 | +
|
| 68 | + Returns |
| 69 | + ------- |
| 70 | + resampled : `spatialimage` or ndarray |
| 71 | + The data imaged after resampling to reference space. |
| 72 | +
|
| 73 | + """ |
| 74 | + if reference is not None and isinstance(reference, (str, Path)): |
| 75 | + reference = _nbload(str(reference)) |
| 76 | + |
| 77 | + _ref = ( |
| 78 | + transform.reference if reference is None else SpatialReference.factory(reference) |
| 79 | + ) |
| 80 | + |
| 81 | + if _ref is None: |
| 82 | + raise TransformError("Cannot apply transform without reference") |
| 83 | + |
| 84 | + if isinstance(spatialimage, (str, Path)): |
| 85 | + spatialimage = _nbload(str(spatialimage)) |
| 86 | + |
| 87 | + data = np.asanyarray(spatialimage.dataobj) |
| 88 | + targets = ImageGrid(spatialimage).index( # data should be an image |
| 89 | + _as_homogeneous(transform.map(_ref.ndcoords.T), dim=_ref.ndim) |
| 90 | + ) |
| 91 | + |
| 92 | + resampled = ndi.map_coordinates( |
| 93 | + data, |
| 94 | + targets.T, |
| 95 | + output=output_dtype, |
| 96 | + order=order, |
| 97 | + mode=mode, |
| 98 | + cval=cval, |
| 99 | + prefilter=prefilter, |
| 100 | + ) |
| 101 | + |
| 102 | + if isinstance(_ref, ImageGrid): # If reference is grid, reshape |
| 103 | + hdr = None |
| 104 | + if _ref.header is not None: |
| 105 | + hdr = _ref.header.copy() |
| 106 | + hdr.set_data_dtype(output_dtype or spatialimage.get_data_dtype()) |
| 107 | + moved = spatialimage.__class__( |
| 108 | + resampled.reshape(_ref.shape), |
| 109 | + _ref.affine, |
| 110 | + hdr, |
| 111 | + ) |
| 112 | + return moved |
| 113 | + |
| 114 | + return resampled |
0 commit comments