From 07fc4c17e05732b2b6915f5a793da30b5070a7f7 Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauldmccarthy@gmail.com> Date: Sun, 21 Jul 2019 13:43:35 +0100 Subject: [PATCH] ENH: resampleToReference now accepts a custom matrix, allowing us to apply a transformation (e.g. FLIRT registration) during the resampling. Missed imports in deprecated fsl.utils.transform --- fsl/utils/image/resample.py | 38 ++++++++++++++++++++++++++++++++----- fsl/utils/transform.py | 4 +++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/fsl/utils/image/resample.py b/fsl/utils/image/resample.py index bf11d7a4e..1aa52b9d2 100644 --- a/fsl/utils/image/resample.py +++ b/fsl/utils/image/resample.py @@ -39,7 +39,7 @@ def resampleToPixdims(image, newPixdims, **kwargs): return resample(image, newShape, **kwargs) -def resampleToReference(image, reference, **kwargs): +def resampleToReference(image, reference, matrix=None, **kwargs): """Resample ``image`` into the space of the ``reference``. This is a wrapper around :func:`resample` - refer to its documenttion @@ -49,6 +49,7 @@ def resampleToReference(image, reference, **kwargs): along the spatial (first three) dimensions. :arg image: :class:`.Image` to resample + :arg matrix: Optional world-to-world affine alignment matrix :arg reference: :class:`.Nifti` defining the space to resample ``image`` into """ @@ -56,6 +57,9 @@ def resampleToReference(image, reference, **kwargs): oldShape = list(image.shape) newShape = list(reference.shape[:3]) + if matrix is None: + matrix = np.eye(4) + # If the input image is >3D, pad the # new shape so that we only resample # along the first 3 dimensions. @@ -64,7 +68,9 @@ def resampleToReference(image, reference, **kwargs): # Align the two images together # via their vox-to-world affines. - matrix = affine.concat(image.worldToVoxMat, reference.voxToWorldMat) + matrix = affine.concat(image.worldToVoxMat, + affine.invert(matrix), + reference.voxToWorldMat) # If the input image is >3D, we # have to adjust the resampling @@ -82,7 +88,12 @@ def resampleToReference(image, reference, **kwargs): kwargs['newShape'] = newShape kwargs['matrix'] = matrix - return resample(image, **kwargs) + data = resample(image, **kwargs)[0] + + # The image is now in the same space + # as the reference, so it inherits + # ref's voxel-to-world affine + return data, reference.voxToWorldMat def resample(image, @@ -113,6 +124,12 @@ def resample(image, particularly on the ``order``, ``matrix``, ``mode`` and ``cval`` arguments. + .. note:: If a custom resampling ``matrix`` is specified, the adjusted + voxel-to-world afffine cannot be calculated by this function, + so ``None`` will be returned instead. + + :arg image: :class:`.Image` object to resample + :arg newShape: Desired shape. May containg floating point values, in which case the resampled image will have shape ``round(newShape)``, but the voxel sizes will have scales @@ -159,7 +176,8 @@ def resample(image, - A ``numpy`` array of shape ``(4, 4)``, containing the adjusted voxel-to-world transformation for the spatial - dimensions of the resampled data. + dimensions of the resampled data, or ``None`` if a ``matrix`` + was provided. """ if sliceobj is None: sliceobj = slice(None) @@ -168,6 +186,8 @@ def resample(image, if mode is None: mode = 'nearest' if origin == 'center': origin = 'centre' + ownMatrix = matrix is None + if origin not in ('centre', 'corner'): raise ValueError('Invalid value for origin: {}'.format(origin)) @@ -218,7 +238,15 @@ def resample(image, matrix[:3, :3] = rotmat matrix[:3, -1] = offsets - matrix = affine.concat(image.voxToWorldMat, matrix) + # We can only adjust the v2w affine if + # the input space and resampling space + # are aligned (e.g. if we're just + # resampling to different dimensions). + # We can't assume this when a custom + # matrix is specified, so we just give + # up and return None. + if ownMatrix: matrix = affine.concat(image.voxToWorldMat, matrix) + else: matrix = None return data, matrix diff --git a/fsl/utils/transform.py b/fsl/utils/transform.py index b8c003968..e682cc1be 100644 --- a/fsl/utils/transform.py +++ b/fsl/utils/transform.py @@ -10,7 +10,9 @@ import fsl.utils.deprecated as deprecated -from fsl.transform.affine import * # noqa +from fsl.transform.affine import * # noqa +from fsl.transform.flirt import (flirtMatrixToSform, # noqa + sformToFlirtMatrix) deprecated.warn('fsl.utils.transform', -- GitLab