Skip to content

fiery.diffeo.flows

Utilities for displacement and transformation fields.

Two closely related objects appear throughout this package:

  • a displacement field stores, at each voxel, the offset (in voxels) from that voxel to its target, so the identity displacement is zero;
  • a transformation field stores the target coordinate itself, so the identity transformation is the sampling grid.

They differ by the identity grid, and add_identity / sub_identity convert between them. Most functions here take displacement fields by default and accept transformation fields through has_identity=True.

A velocity field has the same layout but a different meaning: it is a tangent vector, integrated over unit time by fiery.diffeo.svf.exp (stationary) or fiery.diffeo.shoot.shoot (geodesic) to yield a displacement field.

All fields are (..., *spatial, D) tensor, i.e. channel-last, where D is the number of spatial dimensions.

Functions:

add_identity_

add_identity_(flow)

Add the identity grid to a displacement field, in place.

Parameters:

Name Type Description Default
flow (..., *shape, dim) tensor

Displacement field

required

Returns:

Name Type Description
flow (..., *shape, dim) tensor

Transformation field

sub_identity_

sub_identity_(flow)

Subtract the identity grid from a transformation field, in place.

Parameters:

Name Type Description Default
flow (..., *shape, dim) tensor

Transformation field

required

Returns:

Name Type Description
flow (..., *shape, dim) tensor

Displacement field

add_identity

add_identity(flow)

Add the identity grid to a displacement field.

Parameters:

Name Type Description Default
flow (..., *shape, dim) tensor

Displacement field

required

Returns:

Name Type Description
flow (..., *shape, dim) tensor

Transformation field

sub_identity

sub_identity(flow)

Subtract the identity grid from a transformation field.

Parameters:

Name Type Description Default
flow (..., *shape, dim) tensor

Transformation field

required

Returns:

Name Type Description
flow (..., *shape, dim) tensor

Displacement field

identity

identity(shape, **backend)

Return an identity transformation field.

Parameters:

Name Type Description Default
shape (dim,) sequence of int

Spatial shape of the field.

required
**backend dict

Keyword arguments passed to torch.arange, typically dtype and device.

{}

Returns:

Name Type Description
grid (*shape, dim) tensor

Transformation field

affine_field

affine_field(affine, shape, add_identity=False)

Generate an affine flow field

Parameters:

Name Type Description Default
affine (..., D+1, D+1) tensor

Affine matrix

required
shape (D,) list[int]

Lattice size

required
add_identity bool

If True, return a transformation field (absolute coordinates). Otherwise, return a displacement field.

False

Returns:

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

Affine flow

jacobian

jacobian(flow, bound='circulant', voxel_size=1, has_identity=False, add_identity=None)

Compute the Jacobian of a transformation field

Parameters:

Name Type Description Default
flow (..., *spatial, dim) tensor

Transformation or displacement field

required
bound [list of] {'circulant', 'neumann', 'dirichlet', 'sliding'}

Boundary condition

'circulant'
voxel_size [sequence of] float

Voxel size

1
has_identity bool

Whether the input is a transformation (True) or displacement (False) field.

False
add_identity bool

Add the identity to the Jacobian of the displacement, making it the Jacobian of the transformation.

`has_identity`

Returns:

Name Type Description
jac (..., *spatial, dim, dim) tensor

Jacobian. In each matrix: jac[i, j] = d psi[i] / d x[j]

jacdet

jacdet(flow, bound='circulant', voxel_size=1, has_identity=False, add_identity=True)

Compute the determinant of the Jacobian of a transformation field

Parameters:

Name Type Description Default
flow (..., *spatial, dim) tensor

Transformation or displacement field

required
bound [list of] {'circulant', 'neumann', 'dirichlet', 'sliding'}

Boundary condition

'circulant'
voxel_size [sequence of] float

Voxel size

1
has_identity bool

Whether the input is a transformation (True) or displacement (False) field.

False
add_identity bool

Add the identity to the Jacobian of the displacement, making it the Jacobian of the transformation.

True

Returns:

Name Type Description
det (..., *spatial) tensor

Jacobian determinant.

compose

compose(flow_left, flow_right, bound='circulant', has_identity=False, backend=interpol)

Compute the composition flow_left o flow_right

Parameters:

Name Type Description Default
flow_left (..., *shape, D) tensor

Left-hand side field.

required
flow_right (..., *shape, D) tensor

Right-hand side field.

required
bound [list of] {'circulant', 'neumann', 'dirichlet', 'sliding'}

Boundary conditions.

'circulant'
has_identity bool

Whether the inputs are transformation (True) or displacement (False) fields.

False
backend module

Backend used to resample flow_left.

interpol

Returns:

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

Composed field, in the same convention as the inputs.

compose_jacobian

compose_jacobian(jac, rhs, lhs=None, bound='circulant', has_identity=False, backend=interpol)

Jacobian of the composition (lhs)o(rhs)

Parameters:

Name Type Description Default
jac (..., *spatial, ndim, ndim) tensor

Jacobian of input RHS transformation

required
rhs (..., *spatial, ndim) tensor

Right-hand side transformation

required
lhs (..., *spatial, ndim) tensor

Left-hand side small displacement

`rhs`
bound [list of] {'circulant', 'neumann', 'dirichlet', 'sliding'}

Boundary condition

'circulant'
has_identity bool

Whether the left-hand side is a transformation (True) or displacement (False) field.

False
backend module

Backend used to resample the left-hand side.

interpol

Returns:

Name Type Description
composed_jac (..., *spatial, ndim, ndim) tensor

Jacobian of composition

bracket

bracket(vel_left, vel_right, bound='circulant', has_identity=False, backend=interpol)

Compute the Lie bracket of two stationary velocity fields

The Lie bracket [u, w] is the leading correction term of the BCH formula, which is why exp(u) o exp(w) is not exp(u + w) in general. It is approximated here by u o w - w o u, using the composition of displacement fields.

Parameters:

Name Type Description Default
vel_left (..., *shape, D) tensor

Left-hand side velocity field.

required
vel_right (..., *shape, D) tensor

Right-hand side velocity field.

required
bound [list of] {'circulant', 'neumann', 'dirichlet', 'sliding'}

Boundary conditions.

'circulant'
has_identity bool

Whether the inputs include the identity grid.

False
backend module

Backend used to resample the velocity fields.

interpol

Returns:

Name Type Description
bkt (..., *shape, D) tensor

Lie bracket of the two velocity fields.