Transform Tools
Coordinate transformation and image warping utilities.
Module Reference
Tools for transforming and manipulating ITK transforms.
This module provides the ProcessTransforms class with utilities for working with ITK transforms, including transforming images and contours, generating deformation fields, interpolating between transforms, and correcting spatial folding artifacts.
The tools support various transform operations needed for medical image analysis, particularly in the context of 4D cardiac imaging where transforms are used to track anatomical motion over time.
- class monai_physio.process_transforms.ProcessTransforms(log_level=20)[source]
Utilities for transforming and manipulating ITK transforms.
This class provides a comprehensive set of tools for working with ITK transforms in medical image analysis. It supports transforming various data types (images, contours), generating visualization aids, and performing advanced operations like transform interpolation and spatial folding correction.
The class is particularly useful for 4D cardiac imaging workflows where transforms are used to track anatomical motion over time, requiring operations like transform chaining, interpolation, and quality control.
Key capabilities: - Transform PyVista contours and ITK images - Generate deformation fields from transforms - Interpolate between transforms temporally - Smooth transforms to reduce noise - Combine transforms with spatial masks - Detect and correct spatial folding - Generate visualization grids
Example
>>> transform_tools = ProcessTransforms() >>> # Transform a contour mesh >>> transformed_contour = transform_tools.transform_pvcontour( ... contour, transform, with_deformation_magnitude=True ... ) >>> # Generate deformation field >>> field = transform_tools.generate_field(transform, reference_image)
- combine_displacement_field_transforms(tfm1, tfm2, reference_image, tfm1_weight=1.0, tfm2_weight=1.0, mode='compose', tfm1_blur_sigma=0.0, tfm2_blur_sigma=0.0)[source]
Compose two displacement field transforms.
In
addmode, returns a single displacement field transform with weighted summed vectors. Incomposemode, returns a composite transform containing both weighted displacement field transforms.composefollows ITK’s CompositeTransform convention, where the last-added transform is applied first: the result evaluatestfm1(tfm2(x)), sotfm2is the stage that runs first.In
composemode at unit weights with no blurring there is nothing to apply to the fields, so the inputs are chained as they are and no field is rasterized at all. See the comment on that branch below for what that saves.- Return type:
Transform
- convert_transform_to_displacement_field(tfm, reference_image, np_component_type=<class 'numpy.float64'>, use_reference_image_as_mask=False)[source]
Generate a dense deformation field from an ITK transform.
Converts any ITK transform into a dense displacement field that explicitly stores the displacement vector at each voxel. This is useful for visualization, analysis, and storage of transforms.
- Parameters:
tfm (itk.Transform) – Input transform to convert. Can be any ITK transform type (Affine, BSpline, DisplacementField, etc.)
reference_image (itk.image) – Defines the spatial grid for the output deformation field (spacing, size, origin, direction)
use_reference_image_as_mask (bool) – If True, applies the reference image as a mask to zero out displacement vectors outside the image domain
- Returns:
- Vector image where each voxel contains a displacement
vector [dx, dy, dz] in physical coordinates
- Return type:
itk.image
Example
>>> # Generate deformation field for visualization >>> field = transform_tools.generate_field(registration_transform, reference_ct) >>> # Use as mask to limit field to anatomical regions >>> masked_field = transform_tools.generate_field( ... transform, reference_ct, use_reference_image_as_mask=True ... )
- convert_transform_to_displacement_field_transform(tfm, reference_image)[source]
Convert an ITK transform to a displacement field transform.
- Return type:
DisplacementFieldTransform
- invert_displacement_field_transform(tfm, max_iterations=20, max_error_tolerance=0.05, mean_error_tolerance=0.0005)[source]
Invert a displacement field transform.
Uses SimpleITK’s fixed-point iterative inversion on the input field’s own grid. The defaults are tighter than SimpleITK’s own (10 iterations, 0.1 mm max error) because the fields produced here are not smooth everywhere and converge slowly near their support boundary.
- Parameters:
- Return type:
Transform- Returns:
The inverted displacement field transform.
- invert_transform(tfm, reference_image)[source]
Invert any transform, analytically when the type supports it.
Prefers ITK’s analytic inverse (available for translation, rigid, affine and composites of them) and falls back to rasterizing a displacement field over
reference_imageand inverting that numerically.The analytic inverse is preferred because the fallback is only defined on
reference_image’s grid: outside it the field is zero, so the inverse silently degrades to the identity there.- Parameters:
tfm (itk.Transform) – Transform to invert.
reference_image (itk.Image) – Grid used by the displacement-field fallback.
- Returns:
The inverse transform.
- Return type:
itk.Transform
- transform_pvcontour(contour, tfm, with_deformation_magnitude=False)[source]
Transform PyVista contour meshes using an ITK transform.
Applies an ITK transform to all points in a PyVista PolyData mesh, useful for deforming anatomical contours according to computed registration transforms. Optionally computes deformation magnitude at each point.
- Parameters:
contour (pv.PolyData) – The input contour mesh to transform
tfm (itk.Transform) – ITK transform to apply. Can be a single transform or a list/array containing one transform
with_deformation_magnitude (bool) – If True, adds a “DeformationMagnitude” point data array containing the Euclidean distance each point moved
- Returns:
- The transformed contour mesh with updated point
coordinates and optionally deformation magnitude data
- Return type:
pv.PolyData
Example
>>> # Transform cardiac contour with deformation tracking >>> transformed_heart = transform_tools.transform_pvcontour( ... heart_contour, cardiac_transform, with_deformation_magnitude=True ... ) >>> # Access deformation magnitudes >>> deformation = transformed_heart['DeformationMagnitude']
- transform_dataset(mesh, tfm, with_deformation_magnitude=False)[source]
Transform a PyVista dataset while preserving mesh topology and data arrays.
Applies an ITK point transform to every point in the input dataset and returns a deep copy with the original cells, cell data, and point data preserved. This is appropriate for non-contour datasets such as UnstructuredGrid inputs where casting to PolyData would lose topology.
- Return type:
DataSet
- transform_image(image, transform, reference_image, interpolation_method='linear', background_value=0.0)[source]
Transform an ITK image using a specified transform and interpolation.
Resamples an image according to a geometric transform, using the reference image to define the output grid properties. Different interpolation methods are available depending on data type and quality requirements.
- Parameters:
image (itk.image) – The input image to transform
transform (itk.Transform) – The ITK transform to apply
reference_image (itk.image) – Defines output spacing, size, origin, and direction for the transformed image
interpolation_method (str) – Interpolation method. Options: - “linear”: Linear interpolation (default, good for CT/MR) - “nearest”: Nearest neighbor (preserves discrete values) - “sinc”: Sinc interpolation (highest quality, slower)
background_value (float) – Value written where the reference grid samples outside the input image. Default 0.0, which is right for labelmaps and masks; intensity images need the value that means “no tissue” in their own units – for CT that is -1000 HU (air), not 0 HU (water).
- Returns:
The transformed image resampled to reference grid
- Return type:
itk.image
- Raises:
ValueError – If interpolation_method is not one of the supported options
Example
>>> # Transform CT image with linear interpolation >>> warped_ct = transform_tools.transform_image( ... ct_image, deformation_transform, reference_ct ... ) >>> # Transform label map preserving discrete values >>> warped_labels = transform_tools.transform_image( ... labelmap, transform, reference, interpolation_method='nearest' ... )
- convert_vtk_matrix_to_itk_transform(vtk_mat)[source]
Convert a VTK matrix to an ITK transform.
Converts a VTK matrix object into an equivalent ITK transform. This is useful for interoperability between VTK-based processing (e.g., mesh manipulation) and ITK-based image processing and registration.
- Parameters:
vtk_mat (itk.vtkMatrix) – The input VTK transform to convert
- Returns:
The equivalent ITK transform
- Return type:
itk.Transform
Example
>>> # Convert VTK transform from mesh processing >>> itk_transform = transform_tools.get_itk_transform_from_vtk_transform vtk_transform)
- smooth_transform(tfm, sigma, reference_image)[source]
Smooth a transform using Gaussian filtering to reduce noise.
Applies Gaussian smoothing to the displacement field representation of a transform to reduce noise and create more regularized deformations. This is useful for improving transform quality and reducing artifacts.
- Parameters:
tfm (itk.Transform) – Input transform to smooth
sigma (float) – Standard deviation of Gaussian smoothing kernel in physical units (millimeters). Larger values create more smoothing
reference_image (itk.image) – Defines spatial grid for field generation and smoothing
- Returns:
- DisplacementFieldTransform with smoothed
deformation field
- Return type:
itk.Transform
Example
>>> # Smooth noisy registration transform >>> smooth_transform = transform_tools.smooth_transform( ... noisy_transform, sigma=2.0, reference_ct ... ) >>> # Light smoothing for artifact reduction >>> refined_transform = transform_tools.smooth_transform( ... transform, sigma=0.5, reference_image ... )
- smooth_deformation_field_transform(field, sigma, weight_image=None)[source]
Spread a sparsely sampled deformation field into a continuous one.
fieldis treated as a weighted set of displacement samples rather than as an image: the weighted samples and their weights are each Gaussian-smoothed bysigma(physical millimeters) and then divided, which is a Gaussian-weighted average of the nearby samples. A thin surface shell therefore becomes a continuous deformation that keeps the displacement magnitude the samples carried, instead of being diluted by the empty voxels a plain blur would average in. Far from every sample the smoothed weight vanishes and the field decays to zero.This spread is isotropic and carries the whole displacement vector outward. To restrict that spread to an organ’s surface normal beyond a mask – e.g. so a slip interface such as the pleura or the pericardium does not drag surrounding tissue along tangentially – smooth first with this method, then pass the result to
restrict_deformation_field_to_normal_falloff_outside_mask().- Parameters:
field (itk.Image) – Input vector deformation field, sampled where
weight_imageis non-zero.sigma (float) – Standard deviation of the Gaussian smoothing kernel in physical units (millimeters).
weight_image (Optional[itk.Image]) – Per-voxel sample weight, such as the vertex count
WorkflowInferMovement.create_deformation_field()returns. Omit to weight every voxel holding a non-zero displacement equally, which cannot tell an empty voxel from a genuinely zero-displacement one.
- Returns:
Smoothed field transform.
- Return type:
itk.DisplacementFieldTransform
- Raises:
ValueError – If the field holds no non-zero samples to spread.
- restrict_deformation_field_to_normal_falloff_outside_mask(field, normal_image, mask, direction_offset_mm=0.0, direction_transition_mm=5.0, falloff_distance_mm=20.0)[source]
Restrict a dense field to its normal component and fade it outside a mask.
Inside
maskthe field passes through unchanged, so an organ’s own contents still follow its surface. Beyond it, only the component of the displacement along the surface normal is kept – the expansion and contraction, not the tangential sliding – which is how a slip interface such as the pleura or the pericardium behaves: surrounding tissue is pushed and pulled by the organ without being dragged along it. That normal component then fades to zero byfalloff_distance_mmoutside the mask, so the push does not propagate indefinitely; a dense field (unlike a sparsely sampled one) has no other mechanism to die out.- Parameters:
field (itk.Image) – Dense vector deformation field, e.g. the output of
smooth_deformation_field_transform()(.GetDisplacementField()).normal_image (itk.Image) – Per-voxel surface normal on
field’s grid, dense the same wayfieldis – e.g.smooth_deformation_field_transform()applied to the raw per-vertex normalsWorkflowInferMovement.create_deformation_field()returns, with the samesigma/weight_image. Renormalized internally, so it need not be unit length; voxels where it is near zero (no nearby surface to have spread from) keep their full displacement, having no direction to project onto.mask (itk.Image) – Binary or label image on
field’s grid; any non-zero value marks the organ’s interior.direction_offset_mm (float) – Distance (millimeters) past the mask boundary before the field starts switching to its normal component. The fitted surface and the segmentation of the same organ commonly disagree by about a voxel, so a small offset keeps that disagreement from clipping tangential motion at the boundary itself.
direction_transition_mm (float) – Width (millimeters) of the band, starting at
direction_offset_mm, over which the field blends from its full vector to its normal component. Zero would make the switch a discontinuity that shears neighboring voxels in opposite directions and tears a warped volume.falloff_distance_mm (float) – Distance (millimeters) outside the mask boundary over which the (by then normal-only) displacement fades to zero. This is how far the organ’s push and pull reaches into the tissue around it.
- Returns:
The restricted field transform.
- Return type:
itk.DisplacementFieldTransform
- Raises:
ValueError – If
normal_imageormaskdoes not lie onfield’s grid (size, spacing, origin, direction), or ifdirection_offset_mmis not finite, ordirection_transition_mm/falloff_distance_mmis not a finite value greater than zero.
- combine_transforms_with_masks(transform1, transform2, mask1, mask2, reference_image, max_iter=10, jacobian_threshold=0.1)[source]
Combine two transforms using spatial masks with folding correction.
Merges two transforms by weighting their displacement fields according to provided masks, then iteratively corrects any spatial folding (negative Jacobian determinant) that may result from the combination.
This is useful for combining transforms computed for different anatomical regions (e.g., separate heart and lung registration) into a single coherent transform.
- Parameters:
transform1 (itk.Transform) – First transform to combine
transform2 (itk.Transform) – Second transform to combine
mask1 (itk.Image) – Float mask defining spatial influence of transform1 (0.0 = no influence, 1.0 = full influence)
mask2 (itk.Image) – Float mask defining spatial influence of transform2
reference_image (itk.Image) – Defines output grid properties
max_iter (int) – Maximum iterations for folding correction
jacobian_threshold (float) – Jacobian determinant threshold below which folding is detected and corrected
- Returns:
- DisplacementFieldTransform with combined and
corrected transformation
- Return type:
itk.Transform
Example
>>> # Combine heart and lung transforms >>> combined_transform = transform_tools.combine_transforms_with_masks( ... heart_transform, lung_transform, heart_mask, lung_mask, reference_ct ... )
- compute_jacobian_determinant_from_field(field)[source]
Compute Jacobian determinant of a displacement field.
Calculates the Jacobian determinant at each voxel of a displacement field, which indicates local volume change. Values less than 0 indicate spatial folding, values between 0-1 indicate compression, and values greater than 1 indicate expansion.
- Parameters:
field (itk.Image) – Vector displacement field image
- Returns:
Scalar image containing Jacobian determinant values
- Return type:
itk.Image
Example
>>> jacobian = transform_tools.compute_jacobian_determinant_from_field( deformation_field )
- detect_folding_in_field(jacobian_det, threshold=0.1)[source]
Detect spatial folding in a transform.
Checks for spatial folding by examining the minimum Jacobian determinant value. Folding occurs when the Jacobian determinant becomes negative or very small, indicating non-invertible regions.
- Parameters:
jacobian_det (itk.Image) – Jacobian determinant image
threshold (float) – Threshold below which folding is detected
- Returns:
True if folding is detected, False otherwise
- Return type:
Example
>>> if transform_tools.detect_folding_in_field(jacobian, 0.1): ... print('Spatial folding detected - transform needs correction')
- reduce_folding_in_field(field, jacobian_det, reduction_factor=0.8, threshold=0.1)[source]
Reduce folding by scaling displacement field in problematic regions.
Corrects spatial folding by reducing the magnitude of displacement vectors in regions where the Jacobian determinant is below the threshold. This is a simple but effective approach to maintaining transform invertibility.
- Parameters:
- Returns:
Corrected displacement field with reduced folding
- Return type:
itk.Image
Example
>>> corrected_field = transform_tools.reduce_folding_in_field( ... folded_field, jacobian, reduction_factor=0.7 ... )
- generate_grid_image(reference_image, grid_size=60, line_width=3)[source]
Generate a grid image.
- Return type:
image
- convert_field_to_grid_visualization(tfm, reference_image, grid_size=60, line_width=3)[source]
Generate a visual deformation grid for transform visualization.
Creates a regular grid pattern in the reference image space, then applies the transform to visualize the deformation. The resulting warped grid shows how the transform deforms space and can reveal areas of compression, expansion, or folding.
- Parameters:
tfm (itk.Transform) – Transform to visualize
reference_image (itk.image) – Defines spatial domain and grid properties
grid_size (int) – Number of grid lines in each dimension
- Returns:
Binary image containing the transformed grid pattern
- Return type:
itk.image
Example
>>> # Create deformation visualization grid >>> grid = transform_tools.generate_visual_grid_from_field( ... cardiac_transform, reference_ct, grid_size=20 ... ) >>> # Overlay on original image for visualization
Navigation