Transformations
This section covers spatial transformations in ZarrNii, including affine transforms and displacement fields.
Overview
ZarrNii provides support for spatial transformations through the AffineTransform
and DisplacementTransform
classes. These can be used to apply transformations
derived from performing ANTS registration on downsampled (e.g. level > 3) images, then applied to higher resolution (e.g. level < 3) images. ZarrNii performs
these computations in a block-wise manner using Dask, upsampling the displacement field for a block before applying it. You can also provide a sequence of transforms
to perform composition of transformations to resample in a single step.
Affine Transformations
Creating Affine Transformations
from zarrnii import ZarrNii
from zarrnii.transform import AffineTransform
import numpy as np
# Load a dataset
znimg = ZarrNii.from_nifti("path/to/image.nii")
# Create identity transformation
identity_transform = AffineTransform.identity()
# Create transformation from a matrix
matrix = np.array([
[2.0, 0.0, 0.0, 10.0], # Scale X by 2, translate by 10
[0.0, 2.0, 0.0, -5.0], # Scale Y by 2, translate by -5
[0.0, 0.0, 1.0, 0.0], # No change in Z
[0.0, 0.0, 0.0, 1.0] # Homogeneous coordinates
])
transform = AffineTransform.from_array(matrix)
# Load transformation from text file
transform_from_file = AffineTransform.from_txt("transform.txt")
Applying Transformations
# Apply transformation (requires reference image)
ref_znimg = ZarrNii.from_nifti("path/to/reference.nii")
transformed = znimg.apply_transform(transform, ref_znimg=ref_znimg)
Working with Displacement Transformations
from zarrnii.transform import DisplacementTransform
# Load displacement field from NIfTI file
disp_transform = DisplacementTransform.from_nifti("displacement_field.nii")
# Apply displacement transformation
deformed = znimg.apply_transform(disp_transform, ref_znimg=ref_znimg)
Multiple Transformations
# Apply multiple transformations in sequence
# Each transformation is applied sequentially
result = znimg.apply_transform(transform1, transform2, ref_znimg=ref_znimg)
Coordinate Transformations
# Transform coordinates using the matrix multiplication operator
voxel_coords = np.array([50, 60, 30])
ras_coords = transform @ voxel_coords
# Transform multiple points
points = np.array([[50, 60, 30], [100, 120, 60]]).T # 3xN array
transformed_points = transform @ points
Inverting Transformations
# Get the inverse of a transformation
inverse_transform = transform.invert()
# Apply inverse transformation
restored = transformed_znimg.apply_transform(inverse_transform, ref_znimg=znimg)
Coordinate System Handling
# Update transformation for different orientations
updated_transform = transform.update_for_orientation("RPI", "RAS")
Best Practices
- Use ref_znimg parameter: Always provide a reference image when applying transformations
- Consider coordinate systems: Be aware of voxel vs RAS coordinate conventions
- Memory efficiency: Use lazy evaluation with Dask arrays for large datasets
- Transformation order: Remember that multiple transforms are applied sequentially
See Also
- API Reference for detailed method documentation
- Downsampling and Upsampling for resolution change operations
- Working with Zarr and NIfTI for basic format operations