Skip to content

cornucopia.geometric

This module contains geometric transformations.

ApplyElasticTransform

ApplyElasticTransform(flow=None, controls=None, steps=0, order=3, bound='border', zero_center=False, nearest_if_label=True, dtype=None, device=None, **kwargs)

Bases: FinalTransform

Apply a (deterministic) elastic transform.

See also: ElasticTransform, RandomElasticTransform

Example

A transform can be used to obtain a flow field, instead of an output image, by specifying the returns argument. This flow field can then be applied to another image using the ApplyElasticTransform transform.

f = ElasticTransform(returns="flow")(x)
y = ApplyElasticTransform(flow=f)(x)

It is also possible to specify that the flow field should be read from one of the input arguments at call time, instead of being passed at instantiation time:

f = ElasticTransform(returns="flow")(x)
y = ApplyElasticTransform(flow="flow", consume="flow")(x, flow=f)

Parameters:

Name Type Description Default
flow (C, D, *spatial) tensor | (list | dict)[str | int] | None

Flow field. If not a tensor, it must be a (nested) input key. (if not provided, controls must be provided)

None
controls (C, D, *shape) tensor | (list | dict)[str | int] | None

Spline control points If not a tensor, it must be a (nested) input key. (if not provided, flow must be provided)

None
steps int

Number of scaling and squaring steps

0
order 1..7

Order of the splines that encode the smooth deformation.

3
bound (zeros, border, reflection)

Padding mode used for the deformed image.

'zeros'
zero_center bool

Subtract its mean displacement to the flow field so that it has an empirical mean of zero.

False
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

True

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'controls'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'controls': The control points of the displacement field

make_flow

make_flow(shape, controls=None)

Make a flow field from its spline control points.

Parameters:

Name Type Description Default
shape list of int

Shape of the output flow field

required
controls (C, D, *spatial) tensor

Spline control points (if not provided, self.controls will be used)

None

Returns:

Name Type Description
flow (C, D, *shape) tensor

The flow field

ElasticTransform

ElasticTransform(dmax=0.1, unit='fov', shape=5, bound='border', steps=0, order=3, zero_center=False, nearest_if_label=True, *, dtype=None, device=None, shared=True, **kwargs)

Bases: NonFinalTransform

Elastic transform encoded by cubic splines.

The number of control points is fixed but coefficients are randomly sampled from a uniform distribution.

See also: ElasticTransform, RandomElasticTransform

Parameters:

Name Type Description Default
dmax [list of] float

Max displacement per dimension

0.1
unit (fov, vox)

Unit of dmax.

'fov'
shape [list of] int

Number of spline control points

5
bound (zeros, border, reflection)

Padding mode used for the deformed image.

'zeros'
steps int

Number of scaling-and-squaring integration steps

0
order 1..7

Order of the splines that encode the smooth deformation.

3
zero_center bool

Subtract its mean displacement to the flow field so that it has an empirical mean of zero.

False
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

True

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'controls'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'controls': The control points of the displacement field
shared (channels, tensors, channels + tensors, '')

Apply same transform to all images/channels

Final class-attribute instance-attribute

Final = ApplyElasticTransform

The transform type returned by make_final.

Next class-attribute instance-attribute

Next = ApplyElasticTransform

The transform type returned by make_final.

RandomElasticTransform

RandomElasticTransform(dmax=0.1, shape=5, unit='fov', bound='border', steps=0, order=3, zero_center=False, nearest_if_label=False, *, dtype=None, device=None, shared=True, shared_flow=None, **kwargs)

Bases: NonFinalTransform

Elastic Transform with random parameters.

See also: ElasticTransform, RandomElasticTransform

Example

# Apply the same transform to two images (default)
xform = RandomElasticTransform(dmax=0.2, shape=10)
x, y = xform(x, y)

# Apply one transform per image (but shared across channels)
xform = RandomElasticTransform(dmax=0.2, shape=10, shared='channels')
x, y = xform(x, y)

# Sample a set of transforms, and apply them
xform = RandomElasticTransform(dmax=0.2, shape=10)
a, b, c = [xform.make_final() for _ in range(3)]
x, y, z = a(x), b(y), c(z)

Parameters:

Name Type Description Default
dmax Sampler or float

Sampler or Upper bound for maximum displacement

0.1
shape Sampler or int

Sampler or Upper bound for number of control points

5
unit (fov, vox)

Unit of dmax

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'
steps int

Number of scaling-and-squaring integration steps

0
order int

Spline order

3
zero_center bool

Subtract its mean displacement to the flow field so that it has an empirical mean of zero.

False
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'controls'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'controls': The control points of the displacement field
shared (channels, tensors, channels + tensors, '')

Whether to share random parameters across tensors and/or channels

shared_flow (channels, tensors, channels + tensors, '', None)

Whether to share random field across tensors and/or channels. By default: same as shared

Next class-attribute instance-attribute

Next = ElasticTransform

The transform type returned by make_final(..., max_depth=1).

Final class-attribute instance-attribute

Final = ApplyElasticTransform

The transform type returned by make_final(..., max_depth=inf).

ApplyAffineTransform

ApplyAffineTransform(flow=None, matrix=None, bound='border', nearest_if_label=False, dtype=None, device=None, **kwargs)

Bases: FinalTransform

Apply an affine transform encoded by an affine matrix

Parameters:

Name Type Description Default
flow ([C], D, *spatial) tensor

Flow field

None
matrix ([C], D+1, D+1) tensor

Matrix

None
bound (zeros, border, reflection)

Padding mode

'zeros'
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'matrix'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'matrix': The affine matrix

make_flow

make_flow(shape, matrix=None)

Make a flow field from an affine matrix.

Parameters:

Name Type Description Default
shape list of int

Shape of the output flow field

required
matrix ([C], D+1, D+1) tensor

Affine matrix (if not provided, self.matrix will be used)

None

Returns:

Name Type Description
flow ([C], D, *shape) tensor

The flow field

AffineTransform

AffineTransform(translations=0, rotations=0, shears=0, zooms=0, unit='fov', bound='border', nearest_if_label=False, *, dtype=None, device=None, shared=True, **kwargs)

Bases: NonFinalTransform

Apply an affine transform encoded by translations, rotations, shears and zooms.

The affine matrix is defined as: A = T @ Rx @ Ry @ Rz @ Sx @ Sy Sz @ Z with the center of the field of view used as center of rotation. (A is a matrix so the transforms are applied right to left)

Parameters:

Name Type Description Default
translations [list of] float

Translation (per X/Y/Z)

0
rotations [list of] float

Rotations (about Z/Y/X), in deg

0
shears [list of] float

Translation (about Z/Y/Z)

0
zooms [list of] float

Zoom about 1 (per X/Y/Z)

0
unit (fov, vox)

Unit of translations.

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'matrix'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'matrix': The affine matrix
shared (channels, tensors, channels + tensors, '')

Apply same transform to all images/channels

Final class-attribute instance-attribute

Final = ApplyAffineTransform

The transform type returned by make_final.

Next class-attribute instance-attribute

Next = ApplyAffineTransform

The transform type returned by make_final.

RandomAffineTransform

RandomAffineTransform(translations=0.1, rotations=15, shears=0.012, zooms=0.15, iso=False, unit='fov', bound='border', nearest_if_label=False, *, dtype=None, device=None, shared=True, shared_matrix=None, **kwargs)

Bases: NonFinalTransform

Affine Transform with random parameters.

Parameters:

Name Type Description Default
translations Sampler or [list of] float

Sampler or Upper bound for translation (per X/Y/Z)

0.1
rotations Sampler or [list of] float

Sampler or Upper bound for rotations (about Z/Y/X), in deg

15
shears Sampler or [list of] float

Sampler or Upper bound for shears (about Z/Y/Z)

0.012
zooms Sampler or [list of] float

Sampler or Upper bound for zooms about 1 (per X/Y/Z)

0.15
iso bool

Use isotropic zoom

False
unit (fov, vox)

Unit of translations.

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'matrix'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'matrix': The affine matrix
shared (channels, tensors, channels + tensors, '')

Whether to share random parameters across tensors and/or channels

shared_matrix (channels, tensors, channels + tensors, '', None)

Whether to share matrices across tensors and/or channels. By default: same as shared

Next class-attribute instance-attribute

Next = AffineTransform

The transform type returned by make_final(..., max_depth=1).

Final class-attribute instance-attribute

Final = ApplyAffineTransform

The transform type returned by make_final(..., max_depth=inf).

ApplyAffineElasticTransform

ApplyAffineElasticTransform(flow, controls, affine, bound='border', nearest_if_label=False, backend=None, **kwargs)

Bases: FinalTransform

Determinstic affine+elastic transform

Parameters:

Name Type Description Default
flow (C, D, *spatial) tensor

Flow field (if not provided, controls must be provided)

required
controls (C, D, *shape) tensor

Spline control points (if not provided, flow must be provided)

required
affine ([C], D+1, D+1) tensor

Affine matrix

required
bound str

Padding mode

'border'
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'controls', 'matrix'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'controls': The control points of the nonlinear field
  • 'matrix': The affine matrix

AffineElasticTransform

AffineElasticTransform(dmax=0.1, shape=5, steps=0, translations=0, rotations=0, shears=0, zooms=0, unit='fov', bound='border', patch=None, order=3, zero_center=False, nearest_if_label=False, *, dtype=None, device=None, shared=True, **kwargs)

Bases: NonFinalTransform

Affine + Elastic [+ Patch] transform.

Parameters:

Name Type Description Default
dmax [list of] float

Max displacement per dimension

0.1
shape [list of] int

Number of spline control points

5
steps int

Number of scaling-and-squaring integration steps

0
translations [list of] float

Translation (per X/Y/Z)

0
rotations [list of] float

Rotations (about Z/Y/X), in deg

0
shears [list of] float

Translation (about Z/Y/Z)

0
zooms [list of] float

Zoom about 1 (per X/Y/Z)

0
unit (fov, vox)

Unit of translations and dmax.

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'
patch [list of] int

Size of random patch to extract

None
order int

Spline order

3
zero_center bool

Subtract its mean displacement to the elastic flow field so that it has an empirical mean of zero. This has no effect on the affine component.

False
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'controls', 'matrix'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'controls': The control points of the nonlinear field
  • 'matrix': The affine matrix
shared (channels, tensors, channels + tensors, '')

Apply same transform to all images/channels

Final class-attribute instance-attribute

Final = ApplyAffineElasticTransform

The transform type returned by make_final.

Next class-attribute instance-attribute

Next = ApplyAffineElasticTransform

The transform type returned by make_final.

make_final

make_final(x, max_depth=inf)

Parameters:

Name Type Description Default
x (C, *shape) tensor
required
max_depth int
inf

Returns:

Name Type Description
warp (C, D, *shape) tensor
controls (C, D, *self.shape) tensor
affine (D+1, D+1) tensor

RandomAffineElasticTransform

RandomAffineElasticTransform(dmax=0.1, shape=5, steps=0, translations=0, rotations=0, shears=0, zooms=0, iso=False, unit='fov', bound='border', patch=None, order=3, zero_center=False, nearest_if_label=False, *, dtype=None, device=None, shared=True, shared_flow=None, **kwargs)

Bases: NonFinalTransform

Random Affine + Elastic transform.

Parameters:

Name Type Description Default
dmax Sampler or float

Sampler or Upper bound for maximum displacement

0.1
shape Sampler or int

Sampler or Upper bounds for number of control points

5
steps int

Number of scaling-and-squaring integration steps

0
translations Sampler or [list of] float

Sampler or Upper bound for translation (per X/Y/Z)

0
rotations Sampler or [list of] float

Sampler or Upper bound for rotations (about Z/Y/X), in deg

0
shears Sampler or [list of] float

Sampler or Upper bound for shears (about Z/Y/Z)

0
zooms Sampler or [list of] float

Sampler or Upper bound for zooms about 1 (per X/Y/Z)

0
iso bool

Use isotropic zoom

False
unit (fov, vox)

Unit of translations.

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'
patch [list of] int

Size of random patch to extract

None
order int

Spline order

3
zero_center bool

Subtract its mean displacement to the elastic flow field so that it has an empirical mean of zero. This has no effect on the affine component.

False
nearest_if_label bool

By default, if a tensor has an integer data type, it is deformed using label-specific resampling (each unique label is extracted and resampled using linear interpolation, and an argmax output label map is computed on the fly). If nearest_if_label=True, the entire label map will be resampled at once using nearest-neighbour interpolation.

False

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'controls', 'matrix'}
  • 'input': The input image
  • 'output': The deformed image
  • 'flow': The displacement field
  • 'controls': The control points of the nonlinear field
  • 'matrix': The affine matrix
shared (channels, tensors, channels + tensors, '')

Apply same hyperparameters to all images/channels

shared_flow (channels, tensors, channels + tensors, '', None)

Apply the same random flow to all images/channels. Default: same as shared

Next class-attribute instance-attribute

Next = AffineElasticTransform

The transform type returned by make_final(..., max_depth=1).

Final class-attribute instance-attribute

Final = ApplyAffineElasticTransform

The transform type returned by make_final(..., max_depth=inf).

ApplyAffinePair

ApplyAffinePair(left, right, **kwargs)

Bases: FinalTransform

Deterministic affine pair transform

Parameters:

Name Type Description Default
left Transform

The first transform to apply to the input image

required
right Transform

The second transform to apply to the input image

required

Other Parameters:

Name Type Description
returns [list or dict of] {'left', 'right', 'flow', 'matrix'}
  • 'input': Input image
  • 'left': First transformed image
  • 'right': Second transformed image
  • 'flow': Displacement field that warps right to left
  • 'matrix': Affine matrix that warps right to left (i.e., maps left coordinates to right coordinates)

MakeAffinePair

MakeAffinePair(transform=None, *, returns=('left', 'right'), **kwargs)

Bases: NonFinalTransform

Generate a pair made of the same image transformed in two different ways.

This Transform returns a tuple: (transformed_input, true_transform), where transformed_input has the same layout as the input and true_transform is a dictionary with keys 'flow' and 'affine'.

Parameters:

Name Type Description Default
transform RandomAffineTransform

An instantiated transform.

`RandomAffineTransform()`

Other Parameters:

Name Type Description
returns [list or dict of] {'left', 'right', 'flow', 'matrix'}
  • 'input': Input image
  • 'left': First transformed image
  • 'right': Second transformed image
  • 'flow': Displacement field that warps right to left
  • 'matrix': Affine matrix that warps right to left (i.e., maps left coordinates to right coordinates)

Final class-attribute instance-attribute

Final = ApplyAffinePair

The transform type returned by make_final.

Next class-attribute instance-attribute

Next = ApplyAffinePair

The transform type returned by make_final.

ApplySlicewiseAffineTransform

ApplySlicewiseAffineTransform(matrix, flow=None, slice=-1, spacing=1, subsample=1, bound='border', **kwargs)

Bases: FinalTransform

Precomputed slicewise transform

Parameters:

Name Type Description Default
matrix (Nz, D+1, D+1) tensor

Affine matrices for each slice

required
flow (D, *spatial) tensor

Precomputed flow fields for each slice. If not provided, it will be computed from the matrices.

None
slice (0, 1, 2)

Slice direction

0
spacing int

Spacing between thick slices (as a number of high-res voxels)

1
subsample int

Additional isotropic subsampling

1
bound (zeros, border, reflection)

Padding mode

'zeros'

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'matrix'}
  • 'input': First transformed image
  • 'output': Second transformed image
  • 'flow': Displacement field
  • 'matrix': Stacked affine matrices (one per slice)

make_flow

make_flow(shape, matrix=None)

Compute the flow field for a given shape and matrix.

Parameters:

Name Type Description Default
shape list of int

Shape of the output flow field

required
matrix (Nz, D+1, D+1) tensor

Slicewise affine matrix (if not provided, self.matrix will be used)

None

Returns:

Name Type Description
flow (D, *shape) tensor

The flow field

SlicewiseAffineTransform

SlicewiseAffineTransform(translations=0, rotations=0, shears=0, zooms=0, bulk_translations=0, bulk_rotations=0, bulk_shears=0, bulk_zooms=0, slice=-1, unit='fov', bound='border', spacing=1, subsample=1, *, shared=True, **kwargs)

Bases: NonFinalTransform

Each slice samples the 3D volume using a different transform

Parameters:

Name Type Description Default
translations list of [list of] float

Translation per slice (per X/Y/Z)

0
rotations list of [list of] float

Rotations per slice (about Z/Y/X), in deg

0
shears list of [list of] float

Shears per slice (about Z/Y/Z)

0
zooms list of [list of] float

Zoom about 1 per slice (per X/Y/Z)

0
bulk_translations [list of] float

Bulk translation (per X/Y/Z)

0
bulk_rotations [list of] float

Bulk rotation (about Z/Y/X), in deg

0
bulk_shears l[list of] float

Bulk shear (about Z/Y/Z)

0
bulk_zooms [list of] float

Bulk zoom about 1 (per X/Y/Z)

0
slice (0, 1, 2)

Slice direction

0
unit (fov, vox)

Unit of translations.

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'
spacing int

Spacing between thick slices (as a number of high-res voxels)

1
subsample int

Additional isotropic subsampling

1

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'matrix'}
  • 'input': First transformed image
  • 'output': Second transformed image
  • 'flow': Displacement field
  • 'matrix': Stacked affine matrices (one per slice)
shared (channels, tensors, channels + tensors, '')

Apply same transform to all images/channels

Final class-attribute instance-attribute

Final = ApplySlicewiseAffineTransform

The transform type returned by make_final.

Next class-attribute instance-attribute

Next = ApplySlicewiseAffineTransform

The transform type returned by make_final.

RandomSlicewiseAffineTransform

RandomSlicewiseAffineTransform(translations=0.1, rotations=15, shears=0, zooms=0, bulk_translations=0.05, bulk_rotations=15, bulk_shears=0, bulk_zooms=0, iso=False, slice=-1, spacing=1, subsample=1, shots=2, nodes=8, unit='fov', bound='border', *, shared=True, shared_matrix=None, **kwargs)

Bases: NonFinalTransform

Slicewise3DAffineTransform with random parameters.

Parameters:

Name Type Description Default
translations Sampler or [list of] float or (*, 1|D) tensor

Sampler or Upper bound for translation (per X/Y/Z)

0.1
rotations Sampler or [list of] float or (*, 1|D(D-1)/2) tensor

Sampler or Upper bound for rotations (about Z/Y/X), in deg

15
shears Sampler or [list of] float or (*, 1|D(D-1)/2) tensor

Sampler or Upper bound for shears (about Z/Y/Z)

0
zooms Sampler or [list of] float or (*, 1|D) tensor

Sampler or Upper bound for zooms about 1 (per X/Y/Z)

0
bulk_translations [list of] float

Sampler or Upper bound for Bulk translation (per X/Y/Z)

0.05
bulk_rotations [list of] float

Sampler or Upper bound for Bulk rotation (about Z/Y/X), in deg

15
bulk_shears l[list of] float

Sampler or Upper bound for Bulk shear (about Z/Y/Z)

0
bulk_zooms [list of] float

Sampler or Upper bound for Bulk zoom about 1 (per X/Y/Z)

0
iso bool

Use isotropic zoom

False
slice Sampler or int

Slice direction. If None, a random slice direction is selected.

-1
spacing Sampler or int

Spacing between thick slices (as a number of high-res voxels)

1
subsample Sampler or int

Additional isotropic subsampling

1
shots Sampler or int

Number of interleaved sweeps. Typically, two interleaved sequences of slices are acquired to avoid slice cross talk.

2
nodes Sampler or int

Sampler or Upper bound for the number of nodes in the motion trajectory (encoded by cubic splines). If None, independent motions are sampled for each slice.

8
unit (fov, vox)

Unit of translations.

'fov'
bound (zeros, border, reflection)

Padding mode

'zeros'

Other Parameters:

Name Type Description
returns [list or dict of] {'input', 'output', 'flow', 'matrix'}
  • 'input': First transformed image
  • 'output': Second transformed image
  • 'flow': Displacement field
  • 'matrix': Stacked affine matrices (one per slice)
shared (channels, tensors, channels + tensors, '')

Apply same parameters to all images/channels

shared_matrix (channels, tensors, channels + tensors, '')

Apply same affine matrix to all images/channels. Default: same as shared.

Next class-attribute instance-attribute

Next = SlicewiseAffineTransform

The transform type returned by make_final(..., max_depth=1).

Final class-attribute instance-attribute

Final = ApplySlicewiseAffineTransform

The transform type returned by make_final(..., max_depth=inf).