Skip to content

confusius.registration

registration

Registration module for fUSI data.

Modules:

  • affines

    Affine matrix decomposition and composition utilities.

  • bspline

    B-spline transform helpers for fUSI registration.

  • diagnostics

    Diagnostics returned alongside a registration result.

  • exceptions

    Exceptions raised by registration workflows.

  • motion

    Motion parameter estimation and framewise displacement computation.

  • progress

    Registration progress visualization.

  • resampling

    Volume resampling utilities for fUSI data.

  • volume

    Volume-to-volume registration for fUSI data.

  • volumewise

    Volumewise registration for fUSI data.

  • volumewise_progress

    Progress reporting protocol for register_volumewise.

Classes:

Functions:

MatplotlibRegistrationProgressPlotter

Plot registration progress in real time.

Displays an optimizer metric curve, a composite fixed/moving overlay, or both, updated at every iteration. Works in both a Jupyter notebook and an interactive matplotlib backend (e.g. Qt).

Parameters:

  • registration_method

    (ImageRegistrationMethod) –

    The registration method whose progress to monitor.

  • fixed_img

    (Image) –

    The fixed (reference) image, used to resample the composite view.

  • moving_img

    (Image) –

    The moving image, used to resample the composite view.

  • plot_metric

    (bool, default: True ) –

    Whether to display the optimizer metric over iterations.

  • plot_composite

    (bool, default: True ) –

    Whether to display a blended fixed/moving composite at each iteration. Requires an additional sitk.Resample call per iteration.

  • resample_kwargs

    (dict, default: None ) –

    Extra keyword arguments for the internal resample call at each iteration. Supported keys are interpolation, fill_value, and sitk_threads.

Methods:

  • close

    Finalize the plot when registration ends.

  • update

    Update the plot with the current iteration's data.

Attributes:

  • figure ('Figure') –

    The matplotlib figure used for plotting.

  • metric_values (list[float]) –

    Optimizer metric value recorded at each iteration.

figure property

figure: 'Figure'

The matplotlib figure used for plotting.

Returns:

  • Figure

    The figure instance owned by this monitor.

metric_values property

metric_values: list[float]

Optimizer metric value recorded at each iteration.

Returns:

  • list of float

    Copy of the internal metric value buffer.

close

close() -> None

Finalize the plot when registration ends.

Called at sitkEndEvent.

update

update() -> None

Update the plot with the current iteration's data.

Called at every sitkIterationEvent.

RegistrationAbortedError

Bases: RuntimeError

Raised when a registration run is cancelled before completion.

RegistrationDiagnostics dataclass

Per-call diagnostics for a registration optimization.

Returned as the third element of register_volume. Useful for plotting metric convergence curves, comparing runs, and detecting frames that failed to converge.

Attributes:

  • metric ({'correlation', 'mattes_mi'}) –

    Similarity metric used during optimization, echoed from register_volume's metric argument. Determines the sign and scale of metric_values (SimpleITK always minimizes, so both supported metrics are recorded as negative values).

  • metric_values ((n_iterations,) numpy.ndarray) –

    Similarity metric value recorded at each optimizer iteration, in chronological order.

  • final_metric_value (float) –

    Last value of the metric recorded by the optimizer. Equal to metric_values[-1] when at least one iteration ran.

  • n_iterations (int) –

    Number of iterations actually performed by the optimizer. May be smaller than register_volume's number_of_iterations if the optimizer converged early.

  • stop_condition (str) –

    Human-readable description of the optimizer stop condition. When the registration completes normally, this is SimpleITK's GetOptimizerStopConditionDescription. When the registration is aborted cooperatively, this is a short abort message.

  • status ({'completed', 'aborted'}) –

    Whether the registration ran to completion or returned an intermediate result after cooperative cancellation.

RegistrationProgress

Bases: Protocol

Duck-typed contract for an iteration progress reporter.

Implementations are called from the registration thread (SimpleITK's iteration/end callbacks). They must be safe to call from a non-GUI thread; any GUI side effects must be marshalled via Qt signals or similar.

Methods:

  • close

    Called once at the registration end event.

  • update

    Called at every optimizer iteration event.

close

close() -> None

Called once at the registration end event.

update

update() -> None

Called at every optimizer iteration event.

VolumewiseProgressReporter

Bases: Protocol

Duck-typed contract for register_volumewise progress reporting.

Implementations may be called from worker threads when volumewise registration runs in parallel. Any GUI updates must therefore be marshalled via thread-safe mechanisms such as Qt signals.

Methods:

  • close

    Report that the full volumewise run has ended.

  • frame_completed

    Report that one frame finished and provide its registered output.

close

close() -> None

Report that the full volumewise run has ended.

frame_completed

frame_completed(
    frame_index: int,
    registered_frame: "xr.DataArray",
    diagnostics: "RegistrationDiagnostics",
) -> None

Report that one frame finished and provide its registered output.

Parameters:

  • frame_index
    (int) –

    Index of the completed frame.

  • registered_frame
    (DataArray) –

    Registered frame output.

  • diagnostics
    (RegistrationDiagnostics) –

    Diagnostics collected for the completed frame.

compose_affine

compose_affine(
    T: NDArray[floating],
    R: NDArray[floating],
    Z: NDArray[floating],
    S: NDArray[floating] | None = None,
) -> NDArray[floating]

Compose translations, rotations, zooms, and shears into an affine matrix.

Parameters:

  • T

    ((N,) numpy.ndarray) –

    Translation vector, where N is usually 3 (3D case).

  • R

    ((N, N) numpy.ndarray) –

    Rotation matrix, where N is usually 3 (3D case).

  • Z

    ((N,) numpy.ndarray) –

    Zoom (scale) vector, where N is usually 3 (3D case).

  • S

    ((P,) numpy.ndarray, default: None ) –

    Shear vector filling the upper triangle above the diagonal of the shear matrix. P is the (N-2)-th triangular number (3 for the 3D case). If not provided, no shear is applied.

Returns:

  • (N+1, N+1) numpy.ndarray

    Homogeneous affine transformation matrix.

Notes

Adapted from transforms3d.affines.compose by Matthew Brett et al. (BSD-2-Clause License). See the NOTICE and LICENSE-BSD-2-Clause files for details. Source: https://github.com/matthew-brett/transforms3d

compute_framewise_displacement

compute_framewise_displacement(
    affines: Sequence[NDArray[floating]],
    reference: DataArray,
    mask: NDArray[bool_] | None = None,
) -> dict[str, NDArray[floating]]

Compute framewise displacement from affine transforms.

Framewise displacement measures how much voxels move between consecutive frames after registration. For each voxel, we compute the Euclidean distance between its position at frame t and frame t+1 after applying the affine transforms.

Parameters:

  • affines

    (list[ndarray]) –

    List of affine matrices, one per frame.

  • reference

    (DataArray) –

    Spatial DataArray defining the physical grid (spacing and origin derived from its coordinates).

  • mask

    (ndarray, default: None ) –

    Boolean mask indicating which voxels to include. If not provided, uses all voxels.

Returns:

  • dict

    Dictionary with keys:

    • "mean_fd": Mean framewise displacement per frame.
    • "max_fd": Maximum framewise displacement per frame.
    • "rms_fd": RMS framewise displacement per frame.

Raises:

  • ValueError

    If reference fails fUSI validation, if affines is empty, contains an affine that is not (3, 3) or (4, 4), or mixes 2D and 3D affines, or if reference's dimensionality does not match the affine dimensionality.

  • TypeError

    If any affine entry is not a numpy.ndarray.

References

  1. Power, J. D., Barnes, K. A., Snyder, A. Z., Schlaggar, B. L. & Petersen, S. E. Spurious but systematic correlations in functional connectivity MRI networks arise from subject motion. Neuroimage 59, 2142-2154 

create_motion_dataframe

create_motion_dataframe(
    affines: Sequence[NDArray[floating]],
    reference: DataArray,
    mask: NDArray[bool_] | None = None,
    time_coords: NDArray[floating] | None = None,
) -> DataFrame

Create a DataFrame with motion parameters and framewise displacement.

Parameters:

  • affines

    (list[ndarray]) –

    List of affine matrices from registration.

  • reference

    (DataArray) –

    Spatial DataArray defining the physical grid for framewise displacement computation.

  • mask

    (ndarray, default: None ) –

    Boolean mask for FD computation.

  • time_coords

    (ndarray, default: None ) –

    Time coordinates for each frame.

Returns:

  • DataFrame

    DataFrame with columns determined by the affine dimensionality.

    2D affines:

    • rotation: In-plane rotation angle in radians.
    • trans_<dim>: Translations along the DataArray's two named spatial axes (mm), reported in named-axis order.

    3D affines:

    • rot_x, rot_y, rot_z: Rotation angles around the DataArray's x, y, and z axes, in radians.
    • trans_x, trans_y, trans_z: Translations along the DataArray's x, y, and z axes (mm), even when one spatial axis is singleton.

    Both: - mean_fd: Mean framewise displacement (mm). - max_fd: Maximum framewise displacement (mm). - rms_fd: RMS framewise displacement (mm).

    Motion columns are reported in named-axis order (x, y, z), even when the input DataArray stores its spatial dimensions in a different order such as (z, y, x).

Raises:

  • ValueError

    If reference fails fUSI validation, if affines is empty, contains an affine that is not (3, 3) or (4, 4), or mixes 2D and 3D affines, or if reference's dimensionality does not match the affine dimensionality.

  • TypeError

    If any affine entry is not a numpy.ndarray.

decompose_affine

Decompose a 4x4 homogeneous affine into translation, rotation, zoom, shear.

Decomposes A44 into T, R, Z, S such that::

Smat = np.array([[1, S[0], S[1]],
                 [0,    1, S[2]],
                 [0,    0,    1]])
RZS = R @ np.diag(Z) @ Smat
A44[:3, :3] = RZS
A44[:3,  3] = T

Parameters:

  • A44

    ((4, 4) numpy.ndarray) –

    Homogeneous affine matrix.

Returns:

  • T ( (3,) numpy.ndarray ) –

    Translation vector.

  • R ( (3, 3) numpy.ndarray ) –

    Rotation matrix.

  • Z ( (3,) numpy.ndarray ) –

    Zoom (scale) vector. May have one negative zoom to avoid a negative determinant in R.

  • S ( (3,) numpy.ndarray ) –

    Shear vector [sxy, sxz, syz] filling the upper triangle of the shear matrix. Zero for pure rotation/zoom affines.

Notes

Adapted from transforms3d.affines.decompose44 by Matthew Brett et al. (BSD-2-Clause License). See the NOTICE and LICENSE-BSD-2-Clause files for details. Source: https://github.com/matthew-brett/transforms3d

See also: Spencer W. Thomas, "Decomposing a matrix into simple transformations", pp 320-323 in Graphics Gems II, James Arvo (ed.), Academic Press, 1991.

extract_motion_parameters

extract_motion_parameters(
    affines: Sequence[NDArray[floating]],
) -> NDArray[floating]

Extract motion parameters from affine matrices.

Decomposes each (N+1, N+1) homogeneous affine into translation and rotation parameters.

For 2D transforms, extracts: [rotation, translation_0, translation_1]. For 3D transforms, extracts: [rotation_0, rotation_1, rotation_2, translation_0, translation_1, translation_2].

Parameters:

  • affines

    (list[ndarray]) –

    List of affine matrices from registration.

Returns:

  • (n_frames, n_params) numpy.ndarray

    Motion parameters array in raw transform-component order.

    • For 2D: n_params = 3 (rotation, t0, t1).
    • For 3D: n_params = 6 (r0, r1, r2, t0, t1, t2).

Raises:

  • ValueError

    If affines is empty, contains a non-square array, an affine that is not (3, 3) or (4, 4), or mixes 2D and 3D affines.

  • TypeError

    If any affine entry is not a numpy.ndarray.

invert_displacement_field

invert_displacement_field(
    field: DataArray,
    *,
    max_iterations: int = 20,
    max_error_tolerance: float = 0.1,
    sitk_threads: int = -1,
) -> DataArray

Invert a dense displacement field DataArray with SimpleITK.

Uses InvertDisplacementFieldImageFilter, a fixed-point iterative solver, on the same grid as field. The inverse maps physical points in the opposite direction of field: if field is a fixed-to-moving pull transform, the returned field is (approximately) the corresponding moving-to-fixed pull transform.

Parameters:

  • field

    (DataArray) –

    Dense displacement field DataArray as produced by sample_displacement_field or sample_displacement_field_like.

  • max_iterations

    (int, default: 20 ) –

    Maximum number of fixed-point iterations.

  • max_error_tolerance

    (float, default: 0.1 ) –

    Maximum error tolerance (mm) at which the solver is considered converged.

  • sitk_threads

    (int, default: -1 ) –

    Number of threads SimpleITK may use internally. Negative values resolve to max(1, os.cpu_count() + 1 + sitk_threads), so -1 means all CPUs, -2 means all minus one, and so on.

Returns:

  • DataArray

    Inverted displacement field DataArray on the same grid as field.

Raises:

  • ValueError

    If field does not look like a valid displacement field DataArray.

register_volume

register_volume(
    moving: DataArray,
    fixed: DataArray,
    *,
    fixed_mask: DataArray | None = ...,
    moving_mask: DataArray | None = ...,
    transform_type: Literal[
        "translation", "rigid", "affine"
    ],
    metric: Literal["correlation", "mattes_mi"] = ...,
    number_of_histogram_bins: int = ...,
    learning_rate: float | Literal["auto"] = ...,
    number_of_iterations: int = ...,
    convergence_minimum_value: float = ...,
    convergence_window_size: int = ...,
    initialization: Literal[
        "center_geometry", "center_moments"
    ]
    | NDArray[floating]
    | None = ...,
    optimizer_weights: list[float] | None = ...,
    mesh_size: tuple[int, int, int] = ...,
    use_multi_resolution: bool = ...,
    shrink_factors: Sequence[int] = ...,
    smoothing_sigmas: Sequence[int] = ...,
    resample: bool = ...,
    resample_interpolation: Literal[
        "linear", "bspline"
    ] = ...,
    fill_value: float | None = ...,
    sitk_threads: int = ...,
    show_progress: bool = ...,
    plot_metric: bool = ...,
    plot_composite: bool = ...,
    progress_plotter: Callable[..., RegistrationProgress]
    | None = None,
    abort_event: Event | None = ...,
) -> tuple[
    DataArray, NDArray[floating], RegistrationDiagnostics
]
register_volume(
    moving: DataArray,
    fixed: DataArray,
    *,
    fixed_mask: DataArray | None = ...,
    moving_mask: DataArray | None = ...,
    transform_type: Literal["bspline"],
    metric: Literal["correlation", "mattes_mi"] = ...,
    number_of_histogram_bins: int = ...,
    learning_rate: float | Literal["auto"] = ...,
    number_of_iterations: int = ...,
    convergence_minimum_value: float = ...,
    convergence_window_size: int = ...,
    initialization: Literal[
        "center_geometry", "center_moments"
    ]
    | NDArray[floating]
    | None = ...,
    optimizer_weights: list[float] | None = ...,
    mesh_size: tuple[int, int, int] = ...,
    use_multi_resolution: bool = ...,
    shrink_factors: Sequence[int] = ...,
    smoothing_sigmas: Sequence[int] = ...,
    resample: bool = ...,
    resample_interpolation: Literal[
        "linear", "bspline"
    ] = ...,
    fill_value: float | None = ...,
    sitk_threads: int = ...,
    show_progress: bool = ...,
    plot_metric: bool = ...,
    plot_composite: bool = ...,
    progress_plotter: Callable[..., RegistrationProgress]
    | None = None,
    abort_event: Event | None = ...,
) -> tuple[DataArray, DataArray, RegistrationDiagnostics]
register_volume(
    moving: DataArray,
    fixed: DataArray,
    *,
    fixed_mask: DataArray | None = ...,
    moving_mask: DataArray | None = ...,
    metric: Literal["correlation", "mattes_mi"] = ...,
    number_of_histogram_bins: int = ...,
    learning_rate: float | Literal["auto"] = ...,
    number_of_iterations: int = ...,
    convergence_minimum_value: float = ...,
    convergence_window_size: int = ...,
    initialization: Literal[
        "center_geometry", "center_moments"
    ]
    | NDArray[floating]
    | None = ...,
    optimizer_weights: list[float] | None = ...,
    mesh_size: tuple[int, int, int] = ...,
    use_multi_resolution: bool = ...,
    shrink_factors: Sequence[int] = ...,
    smoothing_sigmas: Sequence[int] = ...,
    resample: bool = ...,
    resample_interpolation: Literal[
        "linear", "bspline"
    ] = ...,
    fill_value: float | None = ...,
    sitk_threads: int = ...,
    show_progress: bool = ...,
    plot_metric: bool = ...,
    plot_composite: bool = ...,
    progress_plotter: Callable[..., RegistrationProgress]
    | None = None,
    abort_event: Event | None = ...,
) -> tuple[
    DataArray, NDArray[floating], RegistrationDiagnostics
]
register_volume(
    moving: DataArray,
    fixed: DataArray,
    *,
    fixed_mask: DataArray | None = None,
    moving_mask: DataArray | None = None,
    transform_type: Literal[
        "translation", "rigid", "affine", "bspline"
    ] = "rigid",
    metric: Literal[
        "correlation", "mattes_mi"
    ] = "correlation",
    number_of_histogram_bins: int = 50,
    learning_rate: float | Literal["auto"] = "auto",
    number_of_iterations: int = 100,
    convergence_minimum_value: float = 1e-06,
    convergence_window_size: int = 10,
    initialization: Literal[
        "center_geometry", "center_moments"
    ]
    | NDArray[floating]
    | None = "center_geometry",
    optimizer_weights: list[float] | None = None,
    mesh_size: tuple[int, int, int] = (10, 10, 10),
    use_multi_resolution: bool = False,
    shrink_factors: Sequence[int] = (6, 2, 1),
    smoothing_sigmas: Sequence[int] = (6, 2, 1),
    resample: bool = True,
    resample_interpolation: Literal[
        "linear", "bspline"
    ] = "linear",
    fill_value: float | None = None,
    sitk_threads: int = -1,
    show_progress: bool = False,
    plot_metric: bool = True,
    plot_composite: bool = True,
    progress_plotter: Callable[..., RegistrationProgress]
    | None = None,
    abort_event: Event | None = None,
) -> tuple[
    DataArray,
    NDArray[floating] | DataArray,
    RegistrationDiagnostics,
]

Register a single 2D or 3D volume to a fixed reference.

Voxel spacing and origin are automatically extracted from the DataArray coordinates. Both inputs must be spatial-only (no time dimension).

Parameters:

  • moving

    (DataArray) –

    Volume to register to fixed. Must be 2D or 3D.

  • fixed

    (DataArray) –

    Reference volume. Must be 2D or 3D. Need not have the same shape as moving. When spatial coordinate units metadata is present on both moving and fixed, it must match.

  • fixed_mask

    (DataArray, default: None ) –

    Mask for the fixed image. Must have boolean dtype and match the shape and coordinates of fixed. When provided, only voxels where the mask is True are used for computing the similarity metric. This is useful when the fixed image contains NaN values or regions that should be excluded from registration.

  • moving_mask

    (DataArray, default: None ) –

    Mask for the moving image. Must have boolean dtype and match the shape and coordinates of moving. When provided, only voxels where the mask is True are used for computing the similarity metric. This is useful when the moving image contains NaN values or regions that should be excluded from registration.

  • transform_type

    ((translation, rigid, affine, bspline), default: "translation" ) –

    Transform model to use during registration. "translation" allows only shifts. "rigid" adds rotation. "affine" adds scaling and shearing. "bspline" fits a non-linear deformable transform (see mesh_size).

  • metric

    ((correlation, mattes_mi), default: "correlation" ) –

    Similarity metric. "correlation" (normalized cross-correlation) is appropriate for same-modality registration. "mattes_mi" (Mattes mutual information) is better suited for multi-modal registration or when the intensity relationship between images is non-linear.

  • number_of_histogram_bins

    (int, default: 50 ) –

    Number of histogram bins used by Mattes mutual information. Only relevant when using "mattes_mi" metric.

  • learning_rate

    (float or auto, default: "auto" ) –

    Optimizer step size in normalized units. "auto" re-estimates the rate at every iteration. A float uses that value directly; if registration diverges or fails to converge, reduce it.

  • number_of_iterations

    (int, default: 100 ) –

    Maximum number of optimizer iterations.

  • convergence_minimum_value

    (float, default: 1e-6 ) –

    Value used for convergence checking in conjunction with the energy profile of the similarity metric that is estimated in the given window size.

  • convergence_window_size

    (int, default: 10 ) –

    Number of values of the similarity metric which are used to estimate the energy profile of the similarity metric.

  • initialization

    ((center_geometry, center_moments), default: "center_geometry" ) –

    Initial transform mapping fixed to moving coordinates, applied before optimization:

    • "center_geometry": aligns image centers.
    • "center_moments": aligns centers of mass.
    • (N+1, N+1) homogeneous affine matrix: uses a precomputed affine transform.
    • None: uses the identity transform.

    For transform_type="bspline", centering modes are ignored but affine initialization is supported.

  • optimizer_weights

    (list of float, default: None ) –

    Per-parameter weights applied on top of the auto-estimated physical shift scales. None uses identity weights (all ones). A list is passed directly to SimpleITK's SetOptimizerWeights; its length must match the number of transform parameters (3 for 2D rigid, 6 for 3D rigid, 6 for 2D affine, 12 for 3D affine). The weight for each parameter is multiplied into the effective step size: 0 freezes a parameter entirely, values in (0, 1) slow it down, and 1 leaves it unchanged. For the 3D Euler transform the parameter order is [angleX, angleY, angleZ, tx, ty, tz]; to disable rotations around x and y set weights to [0, 0, 1, 1, 1, 1].

  • mesh_size

    (tuple of int, default: (10, 10, 10) ) –

    Number of B-spline mesh nodes along each spatial dimension. Only used when transform_type="bspline".

  • use_multi_resolution

    (bool, default: False ) –

    Whether to use a multi-resolution pyramid during registration. When True, registration proceeds from a coarse downsampled version of the images to the full resolution, which improves convergence for large displacements and reduces the risk of local minima.

  • shrink_factors

    (sequence of int, default: (6, 2, 1) ) –

    Downsampling factor at each pyramid level, from coarsest to finest. Must have the same length as smoothing_sigmas. Only used when use_multi_resolution=True.

  • smoothing_sigmas

    (sequence of int, default: (6, 2, 1) ) –

    Gaussian smoothing sigma (in voxels) applied at each pyramid level, from coarsest to finest. Must have the same length as shrink_factors. Only used when use_multi_resolution=True.

  • resample

    (bool, default: True ) –

    Whether to resample the moving volume onto the fixed grid after estimating the transform. When True, the output is resampled onto the fixed grid and its coordinates match fixed. When False, only the transform is computed and the moving volume is returned unchanged with its original coordinates.

  • resample_interpolation

    ((linear, bspline), default: "linear" ) –

    Interpolator used when resampling the moving volume onto the fixed grid. "linear" is fast and appropriate for most cases. "bspline" (3rd-order B-spline) produces smoother results and reduces ringing, useful for atlas registration. Only used when resample=True.

  • fill_value

    (float, default: None ) –

    Fill value for voxels that fall outside the moving image's field of view after resampling. Applied to both the final registered output (when resample=True) and the progress composite overlay (when show_progress=True and plot_composite=True). If not provided, defaults to the minimum value of moving, which renders out-of-FOV regions as background regardless of intensity scale (important for dB data where 0 is maximum intensity).

  • sitk_threads

    (int, default: -1 ) –

    Number of threads SimpleITK may use internally. Negative values resolve to max(1, os.cpu_count() + 1 + sitk_threads), so -1 means all CPUs, -2 means all minus one, and so on. You may want to set this to a lower value or 1 when running multiple registrations in parallel (e.g. with joblib) to avoid over-subscribing the CPU.

  • show_progress

    (bool, default: False ) –

    Whether to display a live progress plot during registration. The plot is shown in a Jupyter notebook or in an interactive matplotlib window depending on the active backend.

  • plot_metric

    (bool, default: True ) –

    Whether to include the optimizer metric curve in the progress plot. Ignored when show_progress=False.

  • plot_composite

    (bool, default: True ) –

    Whether to include a fixed/moving composite overlay in the progress plot. Requires resampling the moving image at every iteration. Ignored when show_progress=False.

  • progress_plotter

    (callable, default: None ) –

    Factory that builds the progress reporter, called inside register_volume as progress_plotter(registration_method, fixed_img, moving_img, *, plot_metric, plot_composite, resample_kwargs). Here resample_kwargs carries interpolation, fill_value, and sitk_threads. The returned object must implement the RegistrationProgress protocol (update() / close()). If not provided, the default MatplotlibRegistrationProgressPlotter is used. Ignored when show_progress=False. Custom factories are expected to be safe to call from a non-GUI thread; GUI side effects must be marshalled via thread-safe primitives such as Qt signals.

  • abort_event

    (Event, default: None ) –

    Cooperative cancellation flag. If set before or during optimisation, the registration stops at the next SimpleITK iteration boundary and returns the current intermediate result with diagnostics.status="aborted".

Returns:

  • registered ( DataArray ) –

    When resample=True, the moving volume resampled onto the fixed grid with coordinates matching fixed and physical-space affines inherited from fixed. When resample=False, the original moving volume with its original coordinates and attributes.

  • transform ( (N+1, N+1) numpy.ndarray or xarray.DataArray or None ) –

    Estimated registration transform. For linear transforms ("translation", "rigid", "affine"), returns a homogeneous affine matrix of shape (N+1, N+1) in physical space, where N is the spatial dimensionality (2 or 3). Follows SimpleITK's pull/inverse convention: the matrix maps fixed-space coordinates to moving-space coordinates. For transform_type="bspline", returns an xarray.DataArray containing the B-spline control-point grid, not a dense deformation field. The first dimension is component with length N, followed by spatial dimensions in ConfUSIus order (("y", "x") in 2D or ("z", "y", "x") in 3D). The coordinate values along each spatial axis are the physical positions of the control points. Attributes include type = "bspline_transform", the spline order, and the control-grid direction matrix. When an affine initialization was also supplied, the DataArray also includes attrs["affines"]["bspline_initialization"] so that the full composite transform (pre-affine + B-spline) can be reconstructed for later resampling.

  • diagnostics ( RegistrationDiagnostics ) –

    Per-iteration metric values, final metric value, iteration count, and the optimizer stop condition. Useful for plotting convergence curves, comparing runs, and detecting registrations that did not converge.

Raises:

  • ValueError

    If either input contains a time dimension or is not 2D or 3D.

  • ValueError

    If moving or fixed contains NaN values.

  • ValueError

    If transform_type, metric, initialization, or resample_interpolation is not a recognised value.

  • ValueError

    If learning_rate is not a positive finite float or "auto".

  • ValueError

    If number_of_iterations, convergence_window_size, or number_of_histogram_bins is not a positive integer.

  • ValueError

    If shrink_factors and smoothing_sigmas have different lengths.

  • ValueError

    If an affine initialization is provided and its shape does not match the image dimensionality.

  • TypeError

    If fixed_mask or moving_mask is not a boolean DataArray.

  • ValueError

    If fixed_mask shape does not match fixed or moving_mask shape does not match moving.

register_volumewise

register_volumewise(
    data: DataArray,
    *,
    reference_time: int = 0,
    n_jobs: int = -1,
    transform: Literal[
        "translation", "rigid", "affine"
    ] = "rigid",
    metric: Literal[
        "correlation", "mattes_mi"
    ] = "correlation",
    number_of_histogram_bins: int = 50,
    learning_rate: float | Literal["auto"] = 0.01,
    number_of_iterations: int = 100,
    convergence_minimum_value: float = 1e-06,
    convergence_window_size: int = 10,
    initialization: Literal[
        "center_geometry", "center_moments"
    ]
    | None = "center_geometry",
    optimizer_weights: list[float] | None = None,
    use_multi_resolution: bool = False,
    shrink_factors: Sequence[int] = (6, 2, 1),
    smoothing_sigmas: Sequence[int] = (6, 2, 1),
    resample_interpolation: Literal[
        "linear", "bspline"
    ] = "linear",
    fill_value: float | None = None,
    show_progress: bool = True,
    progress_reporter: VolumewiseProgressReporter
    | None = None,
    abort_event: Event | None = None,
    keep_diagnostics: bool = False,
) -> DataArray

Register all volumes in a fUSI recording to a reference volume.

Parameters:

  • data

    (DataArray) –

    Input data to register.

  • reference_time

    (int, default: 0 ) –

    Index of the time point to use as registration target.

  • n_jobs

    (int, default: -1 ) –

    Number of parallel jobs. Negative values resolve to max(1, os.cpu_count() + 1 + n_jobs), so -1 means all CPUs, -2 means all minus one, and so on. Use 1 for serial processing.

  • transform

    ((translation, rigid, affine), default: "translation" ) –

    Transform model to use during registration. "translation" allows only shifts. "rigid" adds rotation. "affine" adds scaling and shearing. B-spline is not available for motion correction.

  • metric

    ((correlation, mattes_mi), default: "correlation" ) –

    Similarity metric. "correlation" (normalized cross-correlation) is appropriate for same-modality registration. "mattes_mi" (Mattes mutual information) is better suited for multi-modal registration or when the intensity relationship between images is non-linear.

  • number_of_histogram_bins

    (int, default: 50 ) –

    Number of histogram bins used by Mattes mutual information. Only relevant when metric="mattes_mi".

  • learning_rate

    (float or auto, default: 0.01 ) –

    Optimizer step size in normalised units (after SetOptimizerScalesFromPhysicalShift). "auto" re-estimates the rate at every iteration. A float uses that value directly; if registration diverges or fails to converge, reduce it.

  • number_of_iterations

    (int, default: 100 ) –

    Maximum number of optimizer iterations.

  • convergence_minimum_value

    (float, default: 1e-6 ) –

    Convergence threshold. Optimization stops early when the estimated energy profile falls below this value.

  • convergence_window_size

    (int, default: 10 ) –

    Number of recent metric values used to estimate the energy profile for convergence checking.

  • initialization

    ((center_geometry, center_moments), default: "center_geometry" ) –

    Initial transform mapping fixed to moving coordinates, applied before optimization:

    • "center_geometry": aligns image centers.
    • "center_moments": aligns centers of mass.
    • None: uses the identity transform.
  • optimizer_weights

    (list of float, default: None ) –

    Per-parameter weights applied on top of the auto-estimated physical shift scales. If not provided, identity weights are used. A list is passed directly to SimpleITK's SetOptimizerWeights; its length must match the number of transform parameters (3 for 2D rigid, 6 for 3D rigid, 6 for 2D affine, 12 for 3D affine). The weight for each parameter is multiplied into the effective step size: 0 freezes a parameter entirely, values in (0, 1) slow it down, and 1 leaves it unchanged. For the 3D Euler transform the parameter order is [angleX, angleY, angleZ, tx, ty, tz]; to disable rotations around x and y set weights to [0, 0, 1, 1, 1, 1].

  • use_multi_resolution

    (bool, default: False ) –

    Whether to use a multi-resolution pyramid during registration. When True, registration proceeds from a coarse downsampled version of the images to the full resolution, which improves convergence for large displacements and reduces the risk of local minima.

  • shrink_factors

    (sequence of int, default: (6, 2, 1) ) –

    Downsampling factor at each pyramid level, from coarsest to finest. Must have the same length as smoothing_sigmas. Only used when use_multi_resolution=True.

  • smoothing_sigmas

    (sequence of int, default: (6, 2, 1) ) –

    Gaussian smoothing sigma (in voxels) applied at each pyramid level, from coarsest to finest. Must have the same length as shrink_factors. Only used when use_multi_resolution=True.

  • resample_interpolation

    ((linear, bspline), default: "linear" ) –

    Interpolator used when resampling each volume onto the reference grid. "linear" is fast and appropriate for motion correction. "bspline" (3rd-order B-spline) produces smoother results at the cost of speed.

  • fill_value

    (float, default: None ) –

    Fill value for voxels outside each moving volume's field of view after resampling. If not provided, defaults to that volume's minimum value.

  • show_progress

    (bool, default: True ) –

    Whether to display a progress bar while registering volumes.

  • progress_reporter

    (VolumewiseProgressReporter, default: None ) –

    Thread-safe reporter notified whenever one frame completes. Useful for GUI progress bars or progressively filling an output layer while frames finish.

  • abort_event

    (Event, default: None ) –

    Cooperative cancellation flag shared across frames. If set before or during execution, in-flight frame registrations stop at the next optimiser iteration boundary and this function returns the partial dataset collected so far. Frames that were not started are left blank (filled with the data minimum), and per-frame motion_params rows are marked via the diagnostics status.

  • keep_diagnostics

    (bool, default: False ) –

    Whether to keep the full per-frame RegistrationDiagnostics list on the returned DataArray under attrs["registration_diagnostics"]. Disabled by default because each diagnostics object carries the full optimizer metric trace, which adds up over long recordings. The cheap per-frame summaries (final_metric_value, n_iterations) are always added to motion_params regardless of this flag.

Returns:

  • DataArray

    Registered data with the same coordinates as input, input attributes, and added motion metadata in attrs["reference_time"] and attrs["motion_params"]. motion_params always carries per-frame final_metric_value, n_iterations, and status columns. When keep_diagnostics=True, attrs["registration_diagnostics"] also carries a list of RegistrationDiagnostics (one entry per frame) with the full per-iteration metric trace.

Raises:

  • TypeError

    If n_jobs != 1 and data is backed by an h5py dataset. See Notes.

Notes

SCAN files are HDF5 files loaded lazily via h5py. h5py datasets cannot be pickled, so they cannot be passed to joblib workers for parallel processing. Materialize the data before calling this function:

import confusius as cf

fusi = cf.load("recording.scan").compute()  # load into memory first
fusi = cf.registration.register_volumewise(fusi)

Alternatively, use n_jobs=1 for serial processing (slower but works with lazy SCAN data).

resample_like

resample_like(
    moving: DataArray,
    reference: DataArray,
    transform: NDArray[floating] | DataArray,
    interpolation: Literal[
        "linear", "nearest", "bspline"
    ] = "linear",
    fill_value: float | None = None,
    sitk_threads: int = -1,
) -> DataArray

Resample a volume onto the grid of a reference DataArray.

Convenience wrapper around resample_volume that extracts the output grid (shape, spacing, origin) from reference's coordinates.

Parameters:

  • moving

    (DataArray) –

    2D or 3D spatial DataArray to resample, or 3D+t DataArray with a time dimension. If a time dimension is present, the same transform is applied to all time points.

  • reference

    (DataArray) –

    DataArray defining the output grid. Must be 2D or 3D spatial (no time dimension). When spatial coordinate units metadata is present on both moving and reference, they must match.

  • transform

    ((N+1, N+1) numpy.ndarray or xarray.DataArray) –

    Registration transform, as returned by register_volume. Maps points from the reference physical space to moving physical space (pull/inverse convention).

    • Affine (numpy.ndarray): homogeneous matrix whose translation entries are expressed in the same physical units as moving and reference.
    • B-spline (xarray.DataArray): control-point DataArray.
    • Displacement field (xarray.DataArray): dense field with attrs["type"] == "displacement_field_transform".

    When transform is a DataArray and spatial coordinate units metadata is present on both it and reference, those units must also match.

  • interpolation

    ((linear, nearest, bspline), default: "linear" ) –

    Interpolation method used during resampling.

  • fill_value

    (float, default: None ) –

    Value assigned to voxels that fall outside the moving image's field of view after resampling. If not provided, defaults to float(moving.min()), which renders out-of-FOV voxels as background regardless of intensity scale (important for dB data where 0 is maximum intensity).

  • sitk_threads

    (int, default: os.cpu_count() or 1 ) –

    Number of threads SimpleITK may use for the Resample call. Defaults to all available CPUs.

Returns:

  • DataArray

    Resampled volume on the grid of reference, with reference's coordinates and dimensions, moving's non-spatial attributes, and physical-space affines inherited from reference. If moving had a time dimension, the output will also have a time dimension.

Raises:

  • ValueError

    If reference contains a time dimension or is not 2D or 3D.

resample_volume

resample_volume(
    moving: DataArray,
    transform: NDArray[floating] | DataArray,
    *,
    shape: Sequence[int],
    spacing: Sequence[float],
    origin: Sequence[float],
    dims: Sequence[str],
    interpolation: Literal[
        "linear", "nearest", "bspline"
    ] = "linear",
    fill_value: float | None = None,
    sitk_threads: int = -1,
) -> DataArray

Resample a volume onto an explicit output grid using a pre-computed transform.

Low-level resampling primitive. For the common case of resampling onto the grid of another DataArray, use resample_like instead.

Parameters:

  • moving

    (DataArray) –

    2D or 3D spatial DataArray to resample, or 3D+t or 2D+t DataArray with a time dimension. If a time dimension is present, the same transform is applied to all time points.

  • transform

    ((N+1, N+1) numpy.ndarray or xarray.DataArray) –

    Registration transform, as returned by register_volume.

    • Affine (numpy.ndarray): homogeneous matrix of shape (N+1, N+1) mapping output (fixed) physical coordinates to moving physical coordinates (pull/inverse convention).
    • B-spline (xarray.DataArray): control-point DataArray with attrs["type"] == "bspline_transform" as returned by register_volume(transform="bspline").
    • Displacement field (xarray.DataArray): dense field with attrs["type"] == "displacement_field_transform", as returned by sample_displacement_field or invert_displacement_field.
  • shape

    (sequence of int) –

    Number of voxels along each output axis, in DataArray dimension order.

  • spacing

    (sequence of float) –

    Voxel spacing along each output axis, in DataArray dimension order.

  • origin

    (sequence of float) –

    Physical origin (first voxel centre) along each output axis, in DataArray dimension order.

  • dims

    (sequence of str) –

    Dimension names of the output DataArray.

  • interpolation

    ((linear, nearest, bspline), default: "linear" ) –

    Interpolation method used during resampling.

  • fill_value

    (float, default: None ) –

    Value assigned to voxels that fall outside the moving image's field of view after resampling. If not provided, defaults to float(moving.min()), which renders out-of-FOV voxels as background regardless of intensity scale (important for dB data where 0 is maximum intensity).

  • sitk_threads

    (int, default: -1 ) –

    Number of threads SimpleITK may use internally. Negative values resolve to max(1, os.cpu_count() + 1 + sitk_threads), so -1 means all CPUs, -2 means all minus one, and so on. You may want to set this to a lower value or 1 when running multiple registrations in parallel (e.g. with joblib) to avoid over-subscribing the CPU.

Returns:

  • DataArray

    Resampled volume on the specified grid with moving's attributes. If the input had a time dimension, the output will also have a time dimension. This low-level function does not infer world-space affines for the output grid.

Raises:

  • ValueError

    If moving is not 2D, 3D+t, 3D, or 3D+t.

  • ValueError

    If transform is a numpy array whose shape does not match the spatial image dimensionality.

sample_displacement_field

Sample a registration transform onto an explicit output grid.

Low-level sampling primitive. For the common case of sampling onto the grid of another DataArray, use sample_displacement_field_like instead.

Parameters:

  • transform

    (DataArray) –

    Registration transform DataArray to sample. Currently this accepts B-spline control-point DataArrays produced by register_volume.

  • shape

    (sequence of int) –

    Number of voxels along each output axis, in DataArray dimension order.

  • spacing

    (sequence of float) –

    Voxel spacing along each output axis, in DataArray dimension order.

  • origin

    (sequence of float) –

    Physical origin (first voxel centre) along each output axis, in DataArray dimension order.

  • dims

    (sequence of str) –

    Dimension names of the output displacement field.

  • sitk_threads

    (int, default: -1 ) –

    Number of threads SimpleITK may use internally. Negative values resolve to max(1, os.cpu_count() + 1 + sitk_threads), so -1 means all CPUs, -2 means all minus one, and so on.

Returns:

  • DataArray

    Dense displacement field DataArray with attrs["type"] == "displacement_field_transform", one displacement vector per voxel of the requested grid.

sample_displacement_field_like

sample_displacement_field_like(
    transform: DataArray,
    reference: DataArray,
    *,
    sitk_threads: int = -1,
) -> DataArray

Sample a registration transform onto the grid of a reference DataArray.

Convenience wrapper around sample_displacement_field that extracts the output grid from reference's coordinates.

Parameters:

  • transform

    (DataArray) –

    Registration transform DataArray to sample. Currently this accepts the B-spline control-point DataArrays produced by register_volume.

  • reference

    (DataArray) –

    DataArray defining the output grid. Must be 2D or 3D spatial (no time dimension). When spatial coordinate units metadata is present on both transform and reference, they must match.

  • sitk_threads

    (int, default: -1 ) –

    Number of threads SimpleITK may use internally. Negative values resolve to max(1, os.cpu_count() + 1 + sitk_threads), so -1 means all CPUs, -2 means all minus one, and so on.

Returns:

  • DataArray

    Dense displacement field DataArray sampled on reference's grid.

Raises:

  • ValueError

    If reference contains a time dimension or is not 2D or 3D.