Time-Series Registration

RegisterTimeSeriesImages registers ordered 3D image phases to a reference frame using ANTs, ICON, or the combined ants_icon method.

Class Reference

class physiomotion4d.RegisterTimeSeriesImages(registration_method='ants', log_level=20)[source]

Bases: RegisterImagesBase

Register a time series of images to a fixed image.

This class extends RegisterImagesBase to provide sequential registration of multiple images (time series) to a fixed image. It supports both ANTs and ICON registration methods and can propagate information from prior registrations to initialize subsequent ones.

The registration proceeds in two passes from a reference frame: 1. Forward pass: from reference_frame to the end of the series 2. Backward pass: from reference_frame-1 to the beginning

This bidirectional approach helps maintain temporal coherence in the registration results.

Key features: - Sequential registration of ordered image lists - Support for both ANTs and ICON registration backends - Optional use of prior transforms to initialize next registration - Configurable starting point in the time series - Returns all transforms and loss values for the entire series

registration_method[source]

Registration method to use (‘ants’ or ‘icon’)

Type:

str

registrar

Internal registration object (ANTs or ICON)

Type:

RegisterImagesBase

transform_tools

Utility for transform operations

Type:

TransformTools

Example

>>> # Register a cardiac CT time series
>>> registrar = RegisterTimeSeriesImages(registration_method='ants')
>>> registrar.set_modality('ct')
>>> registrar.set_fixed_image(fixed_image)
>>> registrar.set_number_of_iterations_ants([40, 20, 10])
>>>
>>> # Register all time points to fixed image
>>> result = registrar.register_time_series(
...     moving_images=time_series_images,
...     reference_frame=5,  # Start from middle of cardiac cycle
...     register_reference=True,
...     prior_weight=0.5,
... )
>>>
>>> forward_tfms = result['forward_transforms']  # Moving → Fixed
>>> inverse_tfms = result['inverse_transforms']  # Fixed → Moving
>>> losses = result['losses']
>>>
>>> # Reconstruct time series with optional upsampling
>>> reconstructed = registrar.reconstruct_time_series(
...     moving_images=time_series_images,
...     inverse_transforms=inverse_tfms,
...     upsample_to_fixed_resolution=True,
... )
__init__(registration_method='ants', log_level=20)[source]

Initialize the time series image registration class.

Parameters:
  • registration_method (str) – Registration method to use. Options: ‘ants’ or ‘icon’. Default: ‘ants’

  • log_level (int | str) – Logging level (default: logging.INFO)

Raises:

ValueError – If registration_method is not ‘ants’ or ‘icon’

set_number_of_iterations_ants(number_of_iterations_ants)[source]

Set the number of iterations for ANTs registration.

Parameters:

number_of_iterations_ants (list[int]) – List of iterations for ANTs multi-resolution (e.g., [40, 20, 10] for three resolution levels)

Return type:

None

set_number_of_iterations_icon(number_of_iterations_icon)[source]

Set the number of iterations for ICON registration.

Parameters:

number_of_iterations_icon (int) – Number of fine-tuning steps for ICON

Return type:

None

set_smooth_prior_transform_sigma(smooth_prior_transform_sigma)[source]

Set the sigma for smoothing the prior transform.

Parameters:

smooth_prior_transform_sigma (float) – Sigma for smoothing the prior transform.

Return type:

None

set_mask_dilation(mask_dilation_mm)[source]

Set the dilation of the fixed and moving image masks.

This passes through to the underlying registration method.

Parameters:

mask_dilation_mm (float) – The dilation in millimeters.

Return type:

None

set_modality(modality)[source]

Set the imaging modality for registration optimization.

This passes through to the underlying registration method.

Parameters:

modality (str) – The imaging modality (e.g., ‘ct’, ‘mri’)

Return type:

None

set_fixed_image(fixed_image)[source]

Set the fixed image for registration.

All moving images in the time series will be registered to this fixed image.

Parameters:

fixed_image (itk.Image) – The 3D fixed image

Return type:

None

set_fixed_mask(fixed_mask)[source]

Set a binary mask for the fixed image region of interest.

This passes through to the underlying registration method.

Parameters:

fixed_mask (itk.Image) – Binary mask defining ROI

Return type:

None

register_time_series(moving_images, moving_masks=None, moving_labelmaps=None, reference_frame=0, register_reference=True, prior_weight=0.0)[source]

Register a time series of images to the fixed image.

This method registers an ordered sequence of images to a common fixed frame. Registration proceeds bidirectionally from a reference frame: forward to the end and backward to the beginning.

For each image after the reference image, the method can optionally use the transform from the previous image to initialize the registration, which can improve convergence and temporal coherence.

Parameters:
  • moving_images (list[itk.Image]) – List of 3D images to register

  • moving_masks (list[itk.Image], optional) – List of binary masks, one for each moving image. If None, no masks are used. If provided, must have the same length as moving_images. Default: None

  • moving_labelmaps (list[itk.Image], optional) – Per-frame multi-label segmentations, one for each moving image. If None, no labelmaps are used. If provided, must have the same length as moving_images. Default: None

  • reference_frame (int, optional) – Index of the reference image to register first. Registration proceeds forward from this index to the end, then backward from this index to the beginning. Default: 0

  • register_reference (bool, optional) – If True, register the reference image to the fixed image. If False, use identity transform for the reference image. Default: True

  • prior_weight (float, optional) – Weight (0.0 to 1.0) for using the prior image’s transform to initialize the next registration. 0.0 means no prior information is used (each registration starts from identity). Higher values provide more temporal smoothness but may propagate errors. Default: 0.0

Returns:

Dictionary containing results:
  • ”forward_transforms” (list[itk.Transform]): Transforms from moving to fixed space for each image (warps moving → fixed)

  • ”inverse_transforms” (list[itk.Transform]): Transforms from fixed to moving space for each image (warps fixed → moving)

  • ”losses” (list[float]): Registration loss value for each image

Return type:

dict

Raises:
  • ValueError – If fixed_image is not set

  • ValueError – If reference_frame is out of range

  • ValueError – If prior_weight not in [0, 1]

  • ValueError – If moving_masks length doesn’t match moving_images length

Note

The method compares registration with identity initialization versus prior transform initialization and selects the result with lower loss. This helps prevent error propagation in the temporal sequence.

The fixed image mask can be set using set_fixed_mask() before calling this method.

Example

>>> registrar = RegisterTimeSeriesImages(registration_method='ants')
>>> registrar.set_fixed_image(fixed_image)
>>> registrar.set_fixed_mask(fixed_mask)  # Optional
>>> registrar.set_number_of_iterations_ants([30, 15, 5])
>>>
>>> # Use new intuitive parameter names
>>> result = registrar.register_time_series(
...     moving_images=image_list,
...     moving_masks=mask_list,  # Optional
...     reference_frame=5,
...     register_reference=True,
...     prior_weight=0.5,
... )
>>>
>>> # Access results using new intuitive names
>>> for i, (forward_tfm, loss) in enumerate(
...     zip(result['forward_transforms'], result['losses'])
... ):
...     # Apply forward transform to align moving image i to fixed
...     registered = transform_tools.transform_image(
...         moving_images[i], forward_tfm, fixed_image
...     )
reconstruct_time_series(moving_images, inverse_transforms, upsample_to_fixed_resolution=False)[source]

Reconstruct time series images using inverse transforms.

This method applies the inverse transforms to reconstruct each moving image in the fixed image space. If upsample_to_fixed_resolution is enabled, the reconstructed images will use isotropic spacing (mean of fixed image’s X and Y spacing) while maintaining each moving image’s original origin and direction.

Parameters:
  • moving_images (list[itk.Image]) – List of moving images to reconstruct

  • inverse_transforms (list[itk.Transform]) – List of inverse transforms (one per moving image) from fixed space to moving space

  • upsample_to_fixed_resolution (bool, optional) – If True, reconstructed images will be upsampled to isotropic resolution (mean of fixed image’s X and Y spacing) while maintaining their original origin and direction. Default: False

Returns:

List of reconstructed images in fixed image space

Return type:

list[itk.Image]

Raises:
  • ValueError – If fixed_image is not set

  • ValueError – If lengths of moving_images and inverse_transforms don’t match

Example

>>> registrar = RegisterTimeSeriesImages(registration_method='ants')
>>> registrar.set_fixed_image(fixed_image)
>>>
>>> result = registrar.register_time_series(
...     moving_images=time_series_images,
...     reference_frame=0,
... )
>>>
>>> reconstructed_images = registrar.reconstruct_time_series(
...     moving_images=time_series_images,
...     inverse_transforms=result['inverse_transforms'],
...     upsample_to_fixed_resolution=True,
... )

Basic Usage

import itk

from physiomotion4d import RegisterTimeSeriesImages

images = [itk.imread(f"phase_{idx:02d}.mha") for idx in range(10)]

registrar = RegisterTimeSeriesImages(registration_method="ants")
registrar.set_fixed_image(images[0])

result = registrar.register_time_series(
    moving_images=images,
    reference_frame=0,
    register_reference=False,
)
forward_transforms = result["forward_transforms"]
inverse_transforms = result["inverse_transforms"]

See Also