larmor.registration#

Applying registrations computed by ANTs, FSL or MRtrix3, and inverting them.

Transforms are maps of points in world coordinates (RAS+) in mm. As read from a file, a transform maps points of the reference space to the input space: the direction the tools use to resample an image. Points (streamlines, surfaces) move the other way, so they need the inverse to follow the image.

AffineTransform

A linear transform: p -> A p + t, with (A, t) in a 4x4 matrix.

DisplacementField

A non-linear transform: p -> p + d(p), with d sampled on a grid.

InverseDisplacementField

The inverse of a displacement field, found numerically at each point.

Transform

A map of points from one space to another, in world coordinates (RAS+) in mm.

TransformChain

Transforms applied one after the other: points go through the first first.

TransformPair

A transform given together with its inverse, such as a tool's inverse warp.

apply_transform

Brings an image, tractogram or surface into a reference space.

load_registration

Reads the transform that brings data into a reference space, as tools do.

load_transform

Reads a transform file of any supported format, chosen from the file if needed.

read_ants_transform

Reads a transform written by ANTs (ITK): an affine or a displacement field.

read_flirt_transform

Reads an FSL FLIRT matrix (-omat) as a transform of world points.

read_fsl_warp

Reads an FSL warp field (fnirt --fout, convertwarp, invwarp) as a transform.

read_mrtrix_transform

Reads an MRtrix3 linear transform (mrregister, transformconvert).

read_mrtrix_warp

Reads an MRtrix3 deformation or displacement field as a transform.

transform_file

Brings an image, tractogram or surface file into a reference space.

transform_points

Maps points with a transform.

transform_surface

Moves every vertex of a surface with a transform.

transform_tractogram

Moves every point of a tractogram with a transform.

transform_tractogram_file

Moves the points of a tractogram file with a transform, into a new file.

transform_volume

Resamples an image onto a reference grid through a transform.

class larmor.registration.AffineTransform(matrix)#

A linear transform: p -> A p + t, with (A, t) in a 4x4 matrix.

matrix#

(4, 4) float64, read-only, mapping world points (RAS+, mm) of one space to the other; last row [0, 0, 0, 1].

Type:

numpy.ndarray

map_points(points)#

Maps points to the other space.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The mapped points, shape (N, 3).

Return type:

ndarray

jacobians(points)#

Returns the (N, 3, 3) derivative at the points: A everywhere.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The Jacobian matrices, shape (N, 3, 3).

Return type:

ndarray

inverse()#

Returns the exact inverse.

Returns:

The inverse transform.

Return type:

AffineTransform

class larmor.registration.DisplacementField(grid, displacements)#

A non-linear transform: p -> p + d(p), with d sampled on a grid.

d is interpolated trilinearly between the voxel centres; a point up to half a voxel beyond the outer centres takes the edge values, and a point further out is not moved (d = 0).

grid#

The grid the displacements are sampled on.

Type:

larmor.types.grid.Grid

displacements#

(X, Y, Z, 3) float64, read-only: d at each voxel centre, in world coordinates (RAS+) in mm. NaN where the field is undefined.

Type:

numpy.ndarray

map_points(points)#

Maps points to the other space.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The mapped points, shape (N, 3).

Return type:

ndarray

jacobians(points)#

Returns the (N, 3, 3) derivative at the points: I + grad d.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The Jacobian matrices, shape (N, 3, 3).

Return type:

ndarray

inverse()#

Returns the inverse, computed point by point when it is used.

Returns:

InverseDisplacementField – The inverse field.

Return type:

InverseDisplacementField

class larmor.registration.InverseDisplacementField(field, tolerance=0.0001, max_iterations=200)#

The inverse of a displacement field, found numerically at each point.

For a point y, x with x + d(x) = y is found by the fixed-point iteration x <- y - d(x), starting from x = y, until |x + d(x) - y| is below tolerance. It converges where the field is invertible and smooth (|grad d| < 1), as fields from diffeomorphic registration are. Points where it does not converge within max_iterations are reported in a warning with the largest residual. A tool’s own inverse field, where there is one, avoids the iteration.

field#

The field being inverted.

Type:

larmor.registration.transforms.DisplacementField

tolerance#

The largest residual |x + d(x) - y| accepted, in mm.

Type:

float

max_iterations#

The most iterations per point.

Type:

int

map_points(points)#

Maps points to the other space.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The mapped points, shape (N, 3).

Return type:

ndarray

jacobians(points)#

Returns the (N, 3, 3) derivative at the points: the inverse of I + grad d.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The Jacobian matrices, shape (N, 3, 3).

Return type:

ndarray

inverse()#

Returns the field itself.

Returns:

The field being inverted.

Return type:

DisplacementField

class larmor.registration.Transform(*args, **kwargs)#

A map of points from one space to another, in world coordinates (RAS+) in mm.

Every transform Larmor reads maps points of the reference space (the grid an image is resampled onto) to the input space (where the image’s data lives), the direction the tools themselves use to resample images. Moving points (streamlines, surface vertices) from the input space into the reference space therefore needs the inverse.

map_points(points)#

Maps points to the other space.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The mapped points, shape (N, 3).

Return type:

ndarray

jacobians(points)#

Returns the (N, 3, 3) derivative of map_points at each of the points.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The Jacobian matrices, shape (N, 3, 3).

Return type:

ndarray

inverse()#

Returns the transform that maps the points back.

Returns:

The inverse transform.

Return type:

Transform

class larmor.registration.TransformChain(transforms=<factory>)#

Transforms applied one after the other: points go through the first first.

For images this is the order antsApplyTransforms lists its -t options in: the first transform takes the reference grid’s points, the last gives positions in the input image. A registration with an affine and a warp, written by ANTs as 1Warp.nii.gz and 0GenericAffine.mat, is the chain [warp, affine].

transforms#

The transforms, in the order they are applied to points.

Type:

collections.abc.Sequence[larmor.registration.transforms.Transform]

map_points(points)#

Maps points through every transform in turn.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The mapped points, shape (N, 3).

Return type:

ndarray

jacobians(points)#

Returns the (N, 3, 3) derivative at the points, by the chain rule.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The Jacobian matrices, shape (N, 3, 3).

Return type:

ndarray

inverse()#

Returns the chain of the inverses, in the reverse order.

Returns:

The inverse chain.

Return type:

TransformChain

class larmor.registration.TransformPair(forward, backward)#

A transform given together with its inverse, such as a tool’s inverse warp.

forward#

The transform map_points applies.

Type:

larmor.registration.transforms.Transform

backward#

Its inverse, which inverse returns (as a pair, swapped).

Type:

larmor.registration.transforms.Transform

map_points(points)#

Maps points with forward.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The mapped points, shape (N, 3).

Return type:

ndarray

jacobians(points)#

Returns the (N, 3, 3) derivative of forward at the points.

Parameters:

points (ndarray) – The points, shape (N, 3), in mm, world coordinates (RAS+).

Returns:

The Jacobian matrices, shape (N, 3, 3).

Return type:

ndarray

inverse()#

Returns the pair swapped: backward forward.

Returns:

The pair with backward and forward swapped.

Return type:

TransformPair

larmor.registration.apply_transform(data, transform, *, reference=None, interpolation='linear', reorient=None)#

Brings an image, tractogram or surface into a reference space.

transform maps reference points to the data’s space, as transform files store it and load_registration returns it. An image is resampled with it (transform_volume); the points of a tractogram or surface move with its inverse (transform_tractogram, transform_surface), so that every kind of data lands in the same space.

Parameters:
  • data (Volume | Tractogram | Surface) – A Volume, Tractogram or Surface, in world coordinates (RAS+).

  • transform (Transform) – Maps reference points to the data’s points, in mm.

  • reference (Grid | None) – The reference grid; needed for an image, stored as the reference of a tractogram or surface.

  • interpolation (Literal['nearest', 'linear', 'cubic']) – For an image, as in transform_volume.

  • reorient (Literal['peaks', 'tensor'] | None) – For an image, as in transform_volume.

Returns:

The data in the reference space, of the same type.

Raises:

ValueError – If an image has no reference grid, or as the function used.

Return type:

Volume | Tractogram | Surface

larmor.registration.load_registration(files, *, data_grid=None, reference_grid=None, inverse=False, format=None, warp_type=None, fsl_input_grid=None, fsl_reference_grid=None)#

Reads the transform that brings data into a reference space, as tools do.

The files are those that resample an image into the reference space, listed as antsApplyTransforms lists its -t options: the first takes the reference grid’s points. A pair (file, inverse_file) is a warp with the inverse its tool wrote (ANTs’ InverseWarp, invwarp, warpinvert), which the chain’s inverse then uses instead of inverting numerically. Each file is read as load_transform reads it. With inverse the data goes the other way, from the reference space into the space the files bring images from, and the chain is inverted. The result maps reference points to data points, the direction transform_volume takes; apply_transform uses it for every kind of data.

FSL files need the grids of the FLIRT or FNIRT run’s input and reference images. They default to the data’s grid and reference_grid, swapped with inverse; data without a grid (streamlines, surfaces) needs fsl_input_grid going forward and fsl_reference_grid with inverse.

Parameters:
  • files (Sequence[str | Path | tuple[str | Path, str | Path]]) – The files, or pairs of a warp and the inverse its tool wrote.

  • data_grid (Grid | None) – The grid of the data, if it is an image.

  • reference_grid (Grid | None) – The grid of the reference space.

  • inverse (bool) – Go from the reference space into the space of the files’ inputs.

  • format (str | None) – “ants”, “fsl” or “mrtrix”, when the files alone do not tell.

  • warp_type (str | None) – The warp type of the warp fields, as in load_transform.

  • fsl_input_grid (Grid | None) – The FSL run’s input image grid, if not the default.

  • fsl_reference_grid (Grid | None) – The FSL run’s reference image grid, if not the default.

Returns:

The transform, reference points to data points.

Raises:

ValueError – As load_transform.

Return type:

Transform

larmor.registration.load_transform(path, *, format=None, warp_type=None, fsl_input_grid=None, fsl_reference_grid=None)#

Reads a transform file of any supported format, chosen from the file if needed.

Without format: an ITK text header or a binary mat is ANTs, a text mat is a FLIRT matrix, other text files are MRtrix3, a 5D NIfTI is an ANTs warp and a mif an MRtrix3 deformation field. A 4D NIfTI warp can come from FSL or MRtrix3, so it needs format. Every transform maps reference points to input points, as the tools use them for images; see the format’s reader.

Parameters:
  • path (str | Path) – The transform file.

  • format (str | None) – “ants”, “fsl” or “mrtrix”, when the file alone does not tell.

  • warp_type (str | None) – For a warp field, how it stores where each voxel comes from: “deformation” (positions, MRtrix3’s default) or “displacement” for MRtrix3, “relative” (FSL’s default) or “absolute” for FSL. Checked against the field’s values. ANTs warps are always displacements.

  • fsl_input_grid (Grid | None) – The grid of the FSL run’s input image, needed for FSL files.

  • fsl_reference_grid (Grid | None) – The grid of the FSL run’s reference image, needed for a FLIRT matrix.

Returns:

The transform.

Raises:

ValueError – If the format is unknown or cannot be told, an FSL file lacks a grid, or the warp type does not fit the format or the data.

Return type:

Transform

larmor.registration.read_ants_transform(path)#

Reads a transform written by ANTs (ITK): an affine or a displacement field.

The transform maps points of the fixed image (the reference grid, -r of antsApplyTransforms) to the moving image, the direction antsApplyTransforms uses for images as listed with -t, and antsApplyTransformsToPoints for points. Bringing streamlines from the moving into the fixed space needs its inverse (for a warp, the InverseWarp file antsRegistration writes beside it).

ITK works in LPS coordinates; the transform is converted to RAS+ as read.

Parameters:

path (str | Path) – An affine as a binary mat file (0GenericAffine.mat, MATLAB version 4) or an ITK text file (txt, tfm), of type AffineTransform or MatrixOffsetTransformBase in 3D; or a displacement field as a NIfTI file (1Warp.nii.gz, (X, Y, Z, 1, 3), mm, LPS).

Returns:

The affine or the displacement field, in world coordinates (RAS+) in mm.

Raises:

ValueError – If the file is not one of those, or holds another transform type (convert it with ConvertTransformFile --convertToAffineType).

Return type:

AffineTransform | DisplacementField

larmor.registration.read_flirt_transform(path, input_grid, reference_grid)#

Reads an FSL FLIRT matrix (-omat) as a transform of world points.

FLIRT’s matrix maps the input image’s scaled voxel coordinates (voxel indices times voxel sizes, with the first axis reversed when the image’s affine has a positive determinant) to the reference image’s. It depends on both images, which is why their grids are needed. The transform returned is its inverse in world coordinates: it maps points of the reference image to the input image, the direction used to resample the input onto the reference grid (as flirt -applyxfm does). Moving points from the input into the reference space needs its inverse.

Parameters:
  • path (str | Path) – The text file of 4 rows of 4 numbers.

  • input_grid (Grid) – The grid of FLIRT’s -in image.

  • reference_grid (Grid) – The grid of FLIRT’s -ref image.

Returns:

The affine, reference to input, in world coordinates (RAS+) in mm.

Raises:

ValueError – If the file is not a 4x4 matrix of numbers.

Return type:

AffineTransform

larmor.registration.read_fsl_warp(path, input_grid, *, relative=True)#

Reads an FSL warp field (fnirt --fout, convertwarp, invwarp) as a transform.

The field is defined on the reference image’s grid and holds, in mm of FSL’s scaled voxel coordinates (see read_flirt_transform), where each reference voxel comes from in the input image: as a displacement from the voxel’s own coordinates (relative, FSL’s default) or as the coordinates themselves (absolute, --abs). The transform maps points of the reference image to the input image, the direction applywarp uses to resample the input. Moving points the other way needs its inverse (invwarp’s output, or the numerical inverse).

Fields of spline coefficients (fnirt --cout) are not read; convert them with fnirtfileutils --withaff or convertwarp first.

Parameters:
  • path (str | Path) – The NIfTI file, (X, Y, Z, 3).

  • input_grid (Grid) – The grid of the input image (applywarp’s -i).

  • relative (bool) – Whether the field holds displacements (True) or absolute coordinates. The values are checked against it: absolute coordinates lie near each voxel’s own coordinates, displacements near zero.

Returns:

The displacement field, in world coordinates (RAS+) in mm.

Raises:

ValueError – If the file is not a 4D image with 3 volumes, or its values look like the other kind of field.

Return type:

DisplacementField

larmor.registration.read_mrtrix_transform(path)#

Reads an MRtrix3 linear transform (mrregister, transformconvert).

The matrix is in scanner coordinates (RAS+, mm) and, as mrtransform -linear uses it, maps points of the template (reference) image to the input image. Moving points from the input into the template space needs its inverse.

Parameters:

path (str | Path) – A text file of 3 or 4 rows of 4 numbers; # starts a comment.

Returns:

The affine, in world coordinates (RAS+) in mm.

Raises:

ValueError – If the file is not a 3x4 or 4x4 matrix of numbers.

Return type:

AffineTransform

larmor.registration.read_mrtrix_warp(path, *, displacement=False)#

Reads an MRtrix3 deformation or displacement field as a transform.

A deformation field (warpinit, warpconvert, warpcorrect) holds at each voxel of the template grid the position (scanner coordinates, RAS+, mm) it comes from in the input image; a displacement field holds that position minus the voxel’s own. Either way the transform maps template points to input points, as mrtransform -warp uses it to resample an image. tcktransform uses the same field to move streamlines from the template space into the input space, which is map_points of this transform. NaN marks voxels without a position.

mrregister’s 5D warps (both halves of a symmetric registration) are not read; convert one with warpconvert -type warpfull2deformation first.

Parameters:
  • path (str | Path) – The image (mif, nii, …), (X, Y, Z, 3).

  • displacement (bool) – Whether the field holds displacements instead of positions. The values are checked against it: positions lie near each voxel’s own position, displacements near zero.

Returns:

The displacement field, in world coordinates (RAS+) in mm.

Raises:

ValueError – If the image is not (X, Y, Z, 3), or its values look like the other kind of field.

Return type:

DisplacementField

larmor.registration.transform_file(input_path, output_path, files, *, reference_path=None, inverse=False, interpolation='linear', reorient=None, format=None, warp_type=None, fsl_input_path=None, fsl_reference_path=None)#

Brings an image, tractogram or surface file into a reference space.

The transform files are read with load_registration and applied with apply_transform: an image is resampled as antsApplyTransforms, flirt, applywarp or mrtransform would with the same files and reference, and a tractogram or surface lands in the same space. Uncompressed tck and trk files are streamed in batches (transform_tractogram_file).

Parameters:
  • input_path (str | Path) – An image, a tractogram, or a surface (gii or FreeSurfer).

  • output_path (str | Path) – Where to write the result, of the same kind.

  • files (Sequence[str | Path | tuple[str | Path, str | Path]]) – The transform files, as in load_registration.

  • reference_path (str | Path | None) – An image of the reference space; needed for images and for a trk output.

  • inverse (bool) – Go from the reference space into the space of the files’ inputs.

  • interpolation (Literal['nearest', 'linear', 'cubic']) – For images, as in transform_volume.

  • reorient (Literal['peaks', 'tensor'] | None) – For images, as in transform_volume.

  • format (str | None) – “ants”, “fsl” or “mrtrix”, when the files alone do not tell.

  • warp_type (str | None) – The warp type of the warp fields, as in load_transform.

  • fsl_input_path (str | Path | None) – An image of the FSL run’s input, if not the default.

  • fsl_reference_path (str | Path | None) – An image of the FSL run’s reference, if not the default.

Raises:

ValueError – If the output is the input, an image has no reference, or as the functions used.

larmor.registration.transform_points(points, transform)#

Maps points with a transform.

Parameters:
  • points (ndarray) – (N, 3) points in world coordinates (RAS+) in mm.

  • transform (Transform) – The transform; each point p becomes transform(p).

Returns:

(N, 3) float64, the mapped points.

Return type:

ndarray

larmor.registration.transform_surface(surface, transform, *, reference=None)#

Moves every vertex of a surface with a transform.

Each vertex p becomes transform(p), the same direction as transform_tractogram (the opposite of transform_volume). Where the transform reflects (its Jacobian has a negative determinant at every vertex, such as an affine with a flip), the triangles’ vertex order is reversed so that normals still point out.

Parameters:
  • surface (Surface) – The mesh, in world coordinates (RAS+) in mm.

  • transform (Transform) – Maps the surface’s space to the output space.

  • reference (Grid | None) – The grid of the output space, stored as the result’s reference. None leaves it unknown.

Returns:

A new surface with the moved vertices and the same vertex_data.

Raises:

ValueError – If a vertex lands where the transform is undefined (NaN).

Return type:

Surface

larmor.registration.transform_tractogram(tractogram, transform, *, reference=None)#

Moves every point of a tractogram with a transform.

Each point p becomes transform(p). This is the opposite of transform_volume: the transform that resamples an image from space B onto a grid in space A maps points from A to B. To bring a tractogram from B into A, as the image is brought, pass transform.inverse().

Parameters:
  • tractogram (Tractogram) – The streamlines, in world coordinates (RAS+) in mm.

  • transform (Transform) – Maps the tractogram’s space to the output space.

  • reference (Grid | None) – The grid of the output space, stored as the result’s reference (a TRK file needs one). None leaves it unknown.

Returns:

A new tractogram with the moved points, float32 as always, and the same offsets, point_data and streamline_data.

Raises:

ValueError – If a point lands where the transform is undefined (NaN).

Return type:

Tractogram

larmor.registration.transform_tractogram_file(input_path, output_path, transform, *, reference=None, batch_size=100000)#

Moves the points of a tractogram file with a transform, into a new file.

As transform_tractogram, each point p becomes transform(p). Uncompressed tck and trk files, in and out, are read and written in batches of batch_size streamlines, so memory does not grow with the file; other formats are read whole. The streamlines keep their order, so weights and TSF files of the input belong to the output as they are.

Parameters:
  • input_path (str | Path) – The tractogram file.

  • output_path (str | Path) – The file to write; its extension chooses the format.

  • transform (Transform) – Maps the input’s space to the output space.

  • reference (Grid | None) – The grid of the output space; a trk output needs it.

  • batch_size (int) – Streamlines per batch when streaming.

Returns:

The number of streamlines written.

Raises:

ValueError – As transform_tractogram, or if a trk output has no reference.

Return type:

int

larmor.registration.transform_volume(volume, transform, reference, *, interpolation='linear', reorient=None, fill=0.0)#

Resamples an image onto a reference grid through a transform.

Each voxel of the reference grid, at world position p, takes the image’s value at transform(p). The transform therefore maps points of the reference space to the image’s space, which is the direction transform files store (see load_transform): the same file and the same reference image as for antsApplyTransforms, flirt -applyxfm, applywarp or mrtransform give the same result.

A point within half a voxel beyond the image’s outer voxel centres takes the edge value; a point further out gets fill.

Directions stored in the image are reoriented when reorient says how they are stored. With F the inverse of the transform’s Jacobian at p (the local linear map from the image’s space to the reference space):

  • “peaks”: vectors in groups of 3 per voxel (shape (X, Y, Z, 3K)), each v becoming F v scaled back to the length of v; NaN and zero vectors stay as they are. Needs interpolation="nearest", since averaging vectors of neighbouring voxels would mix different peaks.

  • “tensor”: diffusion tensors as their 6 elements (xx, xy, xz, yy, yz, zz), interpolated element by element, then each D becoming R D R^T, with R the rotation of F (finite strain: R = (F F^T)^(-1/2) F).

Both follow Alexander et al. (2001): the peak rule is their preservation of principal direction applied to one direction, the tensor rule their finite strain. FODs are not reoriented.

Parameters:
  • volume (Volume) – The image, 3D or 4D; each volume of a 4D image is resampled alike.

  • transform (Transform) – Maps reference points to image points, in world mm (RAS+).

  • reference (Grid) – The output grid.

  • interpolation (Literal['nearest', 'linear', 'cubic']) – “nearest” (labels, parcellations; keeps the data type), “linear” (the default) or “cubic” (B-spline of order 3, as ANTs’ BSpline[3]).

  • reorient (Literal['peaks', 'tensor'] | None) – How directions are stored, if they are: “peaks” or “tensor”.

  • fill (float) – The value outside the image.

Returns:

The resampled image on reference, float32 (float64 for a float64 image) unless the interpolation is “nearest”, which keeps the stored values and their scaling.

Raises:

ValueError – If reorient does not match the image’s last axis, or “peaks” is asked for with an interpolation other than “nearest”.

Return type:

Volume

References

Alexander DC, Pierpaoli C, Basser PJ, Gee JC. Spatial transformations of diffusion tensor magnetic resonance images. IEEE Trans Med Imaging 20 (2001) 1131-1139.