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.
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:
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, |
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, |
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 |
True
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'controls'}
|
|
make_flow
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, |
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 |
'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 |
True
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'controls'}
|
|
shared |
(channels, tensors, channels + tensors, '')
|
Apply same transform to all images/channels |
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 |
'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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'controls'}
|
|
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 |
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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'matrix'}
|
|
make_flow
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, |
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 |
'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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'matrix'}
|
|
shared |
(channels, tensors, channels + tensors, '')
|
Apply same transform to all images/channels |
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 |
'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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', '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 |
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, |
required |
controls
|
(C, D, *shape) tensor
|
Spline control points
(if not 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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'controls', '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 |
'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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'controls', 'matrix'}
|
|
shared |
(channels, tensors, channels + tensors, '')
|
Apply same transform to all images/channels |
Final
class-attribute
instance-attribute
The transform type returned by make_final.
Next
class-attribute
instance-attribute
The transform type returned by make_final.
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 |
'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 |
False
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'controls', '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 |
ApplyAffinePair
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'}
|
|
MakeAffinePair
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'}
|
|
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'}
|
|
make_flow
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, |
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 |
'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'}
|
|
shared |
(channels, tensors, channels + tensors, '')
|
Apply same transform to all images/channels |
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 |
'fov'
|
bound
|
(zeros, border, reflection)
|
Padding mode |
'zeros'
|
Other Parameters:
| Name | Type | Description |
|---|---|---|
returns |
[list or dict of] {'input', 'output', 'flow', 'matrix'}
|
|
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 |