diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index aafbf6355b4af1fad83324291892b86829b642b1..2630bdf90fb8990aa2cb351c377482cbc11923ae 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,8 +2,8 @@ This document contains the ``fslpy`` release history in reverse chronological
 order.
 
 
-3.3.0 (Under development)
--------------------------
+3.3.0 (Tuesday 22nd September 2020)
+-----------------------------------
 
 
 Added
@@ -13,6 +13,7 @@ Added
   ``imtest``, ``fsl_abspath``, ``remove_ext``, ``Text2Vest``, and
   ``Vest2Text``.
 * New :func:`.gps` function, wrapping the FSL ``gps`` command.
+* New :func:`.vest.loadVestFile` and :func:`.vest.generateVest` functions.
 
 
 Changed
@@ -22,11 +23,13 @@ Changed
 * Updates to the BIDS filetree specification.
 
 
-Changed
-^^^^^^^
+Fixed
+^^^^^
 
 
-* Adjustments to tests and documentation
+* The :class:`.CoefficientField` class now works with alternate reference
+  images (i.e. a reference image with different dimensions to that which
+  was originally used when the non-linear transformation was calculated).
 
 
 3.2.2 (Thursday 9th July 2020)
diff --git a/fsl/transform/fnirt.py b/fsl/transform/fnirt.py
index 4fa4051c86cd63524a4cca57120c5c1adf5266f9..36dbda8c66f270d03148dd1f5d9a3d521115a46b 100644
--- a/fsl/transform/fnirt.py
+++ b/fsl/transform/fnirt.py
@@ -225,6 +225,27 @@ def _readFnirtCoefficientField(fname, img, src, ref):
     # image voxel coordinates.
     fieldToRefMat = affine.scaleOffsetXform(knotSpacing, 0)
 
+    # But if the provided reference has
+    # different resolution to the
+    # reference that was originally
+    # used to generate the warp field,
+    # we need to adjust the field
+    # accordingly. We assume that the
+    # references are aligned in the FSL
+    # coordinate system, so simply apply
+    # a scaling factor calculated by
+    # dividing the original reference
+    # pixdims by the provided reference
+    # pixdims.
+    refPixdims = np.array([img.header['intent_p1'],
+                           img.header['intent_p2'],
+                           img.header['intent_p3']])
+
+    if not np.all(np.isclose(ref.pixdim[:3], refPixdims)):
+        fieldToRefMat = affine.concat(
+            affine.scaleOffsetXform(refPixdims / ref.pixdim[:3], 0),
+            fieldToRefMat)
+
     return nonlinear.CoefficientField(fname,
                                       src,
                                       ref,
@@ -236,7 +257,7 @@ def _readFnirtCoefficientField(fname, img, src, ref):
                                       fieldToRefMat=fieldToRefMat)
 
 
-def readFnirt(fname, src, ref, defType=None):
+def readFnirt(fname, src, ref, defType=None, intent=None):
     """Reads a non-linear FNIRT transformation image, returning
     a :class:`.DeformationField` or :class:`.CoefficientField` depending
     on the file type.
@@ -247,28 +268,38 @@ def readFnirt(fname, src, ref, defType=None):
     :arg defType:  Deformation type - either ``'absolute'`` or ``'relative'``.
                    Only used if the file is a deformation field. If not
                    provided, is automatically inferred from the data.
+    :arg intent:   NIFTI intent code of ``fname``. e.g.
+                   :attr:`.constants.FSL_FNIRT_DISPLACEMENT_FIELD`. If not
+                   provided, the intent is read from the image header.
     """
 
-    # Figure out whether the file
-    # is a deformation field or
-    # a coefficient field
-
-    img   = fslimage.Image(fname, loadData=False)
-    disps = (constants.FSL_FNIRT_DISPLACEMENT_FIELD,
-             constants.FSL_TOPUP_FIELD)
-    coefs = (constants.FSL_CUBIC_SPLINE_COEFFICIENTS,
-             constants.FSL_DCT_COEFFICIENTS,
-             constants.FSL_QUADRATIC_SPLINE_COEFFICIENTS,
-             constants.FSL_TOPUP_CUBIC_SPLINE_COEFFICIENTS,
-             constants.FSL_TOPUP_QUADRATIC_SPLINE_COEFFICIENTS)
+    if defType not in (None, 'absolute', 'relative'):
+        raise ValueError('defType must be None, "absolute" or "relative" '
+                         '(passed in as {})'.format(defType))
+
+    # Figure out whether the file is a
+    # deformation field or a coefficient
+    # field by checking the intent code.
+    # If the intent is provided, assume
+    # that the caller knows the type of
+    # the field.
+    img    = fslimage.Image(fname, loadData=False)
+    intent = intent or img.intent
+    disps  = (constants.FSL_FNIRT_DISPLACEMENT_FIELD,
+              constants.FSL_TOPUP_FIELD)
+    coefs  = (constants.FSL_CUBIC_SPLINE_COEFFICIENTS,
+              constants.FSL_DCT_COEFFICIENTS,
+              constants.FSL_QUADRATIC_SPLINE_COEFFICIENTS,
+              constants.FSL_TOPUP_CUBIC_SPLINE_COEFFICIENTS,
+              constants.FSL_TOPUP_QUADRATIC_SPLINE_COEFFICIENTS)
 
-    if img.intent in disps:
+    if intent in disps:
         return _readFnirtDeformationField(fname, img, src, ref, defType)
-    elif img.intent in coefs:
+    elif intent in coefs:
         return _readFnirtCoefficientField(fname, img, src, ref)
     else:
-        raise ValueError('Cannot determine type of nonlinear '
-                         'file {}'.format(fname))
+        raise ValueError('Cannot determine type of nonlinear warp field '
+                         '{} (intent code: {})'.format(fname, intent))
 
 
 def toFnirt(field):
diff --git a/fsl/transform/nonlinear.py b/fsl/transform/nonlinear.py
index 77bc212b87d0fc71dfd3f4155fd5ed36a0d12f95..74788a3dc0ebf8b2bcd98a053837858975b027f9 100644
--- a/fsl/transform/nonlinear.py
+++ b/fsl/transform/nonlinear.py
@@ -496,13 +496,11 @@ class CoefficientField(NonLinearTransform):
 
         fdata      = self.data
         nx, ny, nz = self.shape[:3]
-        ix, iy, iz = self.ref.shape[:3]
 
         # Convert the given voxel coordinates
         # into the corresponding coefficient
         # field voxel coordinates
-        x, y, z    = coords.T
-        i, j, k    = affine.transform(coords, self.refToFieldMat).T
+        i, j, k = affine.transform(coords, self.refToFieldMat).T
 
         # i, j, k: coefficient field indices
         # u, v, w: position of the ref voxel
@@ -582,6 +580,10 @@ def convertDeformationType(field, defType=None):
         if field.deformationType == 'absolute': defType = 'relative'
         else:                                   defType = 'absolute'
 
+    if defType not in ('absolute', 'relative'):
+        raise ValueError('defType must be "absolute" or "relative" '
+                         '("{}" passed)'.format(defType))
+
     # Regardless of the conversion direction,
     # we need the coordinates of every voxel
     # in the reference coordinate system.
@@ -601,8 +603,8 @@ def convertDeformationType(field, defType=None):
     # assumed to be) the relative shift. Or,
     # to convert from absolute to relative,
     # we subtract the reference image voxels.
-    if   defType == 'absolute': return field.data + coords
-    elif defType == 'relative': return field.data - coords
+    if defType == 'absolute': return field.data + coords
+    else:                     return field.data - coords
 
 
 def convertDeformationSpace(field, from_, to):
diff --git a/tests/test_transform/test_fnirt.py b/tests/test_transform/test_fnirt.py
index eefc68b64e471dc052ff4fb92b637f56a599a8fa..27ceb40703e5e2506dffb762c59df562153feaf1 100644
--- a/tests/test_transform/test_fnirt.py
+++ b/tests/test_transform/test_fnirt.py
@@ -9,10 +9,13 @@ import os.path as op
 import itertools as it
 
 import numpy as np
+import nibabel as nib
 
 import pytest
 
 import fsl.data.image          as fslimage
+import fsl.utils.tempdir       as tempdir
+import fsl.data.constants      as constants
 import fsl.transform.affine    as affine
 import fsl.transform.nonlinear as nonlinear
 import fsl.transform.fnirt     as fnirt
@@ -51,6 +54,39 @@ def test_readFnirt():
     assert disp.refSpace == 'fsl'
 
 
+def test_readFnirt_defType_intent():
+    src  = op.join(datadir, 'src.nii.gz')
+    ref  = op.join(datadir, 'ref.nii.gz')
+    coef = op.join(datadir, 'coefficientfield.nii.gz')
+    disp = op.join(datadir, 'displacementfield.nii.gz')
+
+    src  = fslimage.Image(src)
+    ref  = fslimage.Image(ref)
+
+    field = fnirt.readFnirt(disp, src, ref, defType='absolute')
+    assert field.deformationType == 'absolute'
+    field = fnirt.readFnirt(disp, src, ref, defType='relative')
+    assert field.deformationType == 'relative'
+
+    img = nib.load(coef)
+    img.header['intent_code'] = 0
+    with tempdir.tempdir():
+        img.to_filename('field.nii.gz')
+
+        with pytest.raises(ValueError):
+            fnirt.readFnirt('field', src, ref)
+
+        field = fnirt.readFnirt(
+            'field', src, ref,
+            intent=constants.FSL_CUBIC_SPLINE_COEFFICIENTS)
+        assert isinstance(field, nonlinear.CoefficientField)
+
+        field = fnirt.readFnirt(
+            'field', src, ref,
+            intent=constants.FSL_FNIRT_DISPLACEMENT_FIELD)
+        assert isinstance(field, nonlinear.DeformationField)
+
+
 def test_toFnirt():
 
     def check(got, exp):
diff --git a/tests/test_transform/test_nonlinear.py b/tests/test_transform/test_nonlinear.py
index 323b6aff94f3e741221a000c96d051fb367476b9..8bfb0c3aba0d7d0746cf48d56b19631dfc1c2536 100644
--- a/tests/test_transform/test_nonlinear.py
+++ b/tests/test_transform/test_nonlinear.py
@@ -311,6 +311,38 @@ def test_CoefficientField_transform():
         assert np.all(np.isclose(gotnp, srccoordsnp[srcspace], **tol))
 
 
+def test_coefficientField_transform_altref():
+
+    # test coordinates (manually determined).
+    # original ref image is 2mm isotropic,
+    # resampled is 1mm. Each tuple contains:
+    #
+    # (src, ref2mm, ref1mm)
+    coords = [
+        ((18.414, 26.579, 25.599), (11, 19, 11), (22, 38, 22)),
+        ((14.727, 22.480, 20.340), ( 8, 17,  8), (16, 34, 16)),
+        ((19.932, 75.616, 27.747), (11, 45,  5), (22, 90, 10))
+    ]
+
+    nldir  = op.join(datadir, 'nonlinear')
+    src    = op.join(nldir, 'src.nii.gz')
+    ref    = op.join(nldir, 'ref.nii.gz')
+    cf     = op.join(nldir, 'coefficientfield.nii.gz')
+
+    src      = fslimage.Image(src)
+    ref2mm   = fslimage.Image(ref)
+    ref1mm   = ref2mm.adjust((1, 1, 1))
+    cfref2mm = fnirt.readFnirt(cf, src, ref2mm)
+    cfref1mm = fnirt.readFnirt(cf, src, ref1mm)
+
+    for srcc, ref2mmc, ref1mmc in coords:
+        ref2mmc = cfref2mm.transform(ref2mmc, 'voxel', 'voxel')
+        ref1mmc = cfref1mm.transform(ref1mmc, 'voxel', 'voxel')
+
+        assert np.all(np.isclose(ref2mmc, srcc, 1e-4))
+        assert np.all(np.isclose(ref1mmc, srcc, 1e-4))
+
+
 def test_coefficientFieldToDeformationField():
 
     nldir = op.join(datadir, 'nonlinear')