Transforms

Base classes

class castalign.base.Transform(**kwargs)[source]

Bases: object

Base class for all transforms.

This is the core transform interface used across CASTalign. A transform maps 3D volume coordinates from one space to another, and can also be applied to full volumetric images through resampling.

Conceptually, transforms in CASTalign are usually either:

  • point-based (see PointTransform), or

  • parameterized transforms that do not use correspondence points.

DEFAULT_PARAMETERS serves two purposes:

  • it provides default values, and

  • it defines the complete set of constructor keyword parameters accepted by that transform class.

Parameter values are stored in self.params and can be edited in the GUI. These are for user-settable controls (for example shifts, scales, toggles), not values that are fit from selected points.

Notes

To implement a new subclass:

  • Implement _transform(points) for forward mapping.

  • Implement invert() for reverse mapping.

  • Implement _fit() if parameters must be derived from point data. _fit() is called during initialization when present.

  • If there is no analytic inverse, subclass PointTransformNoAnalyticInverse.

Any transform must be exactly reconstructible from __repr__ output.

save(filename)[source]

Save this transform to disk as a reconstructible text string.

Parameters:

filename (str or path-like) – Output file path.

Notes

The saved content is repr(self) and is intended to be read back with load().

static load(filename, version=None)[source]

Load a transform from a file written by save().

Parameters:
  • filename (str or path-like) – Input file path containing a transform repr string.

  • version (int or None, optional) – File format version for this transform text. If None, uses the current format version. Set to 1 for older files that may use legacy class names.

Returns:

Reconstructed transform object.

Return type:

Transform

transform(points)[source]

Transform 3D point coordinates from source space to target space.

Use this when you want to move landmarks, annotations, or other coordinate sets into the transformed image space.

Parameters:

points (array-like) – Point coordinates in (z, y, x) order. Accepts either a single point (3,) or many points (N, 3).

Returns:

Transformed coordinates, with the same single-point vs multi-point structure as the input.

Return type:

numpy.ndarray

inverse_transform(points)[source]

Map points from target space back to source space.

Parameters:

points (numpy.ndarray) – Array with shape (N, 3) or a single point (3,).

Returns:

Inverse-transformed points with the same leading shape as input.

Return type:

numpy.ndarray

Notes

Override this for a faster implementation; default is self.invert().transform(points).

invert()[source]

Return the inverse transform.

Use this when you need to map coordinates or images in the opposite direction (target space back to source space).

Returns:

A transform representing the inverse mapping.

Return type:

Transform

Notes

Subclasses must implement this.

origin_and_maxpos(img, output_size=None, force_size=True)[source]

Compute output-space bounds for a transformed image.

This is used internally to inspect or control the output coordinate box before calling transform_image. This is especially useful when you need consistent output extents across multiple transformed volumes.

Parameters:
  • img (numpy.ndarray or ndarray_shifted) – Input 3D image.

  • output_size (None, sequence, or sequence of 2-tuples, optional) – Output bounds.

    • None: tight bounds from transformed corners.

    • (z, y, x): explicit upper bounds from origin 0.

    • ((zmin, zmax), (ymin, ymax), (xmin, xmax)): explicit bounds.

    None values inside explicit bounds are treated as open bounds.

  • force_size (bool, optional) – If True, use explicit bounds exactly. If False, treat them as limits and allow smaller computed bounds.

Returns:

(origin, maxpos) each with shape (3,).

Return type:

tuple of numpy.ndarray

Examples

>>> # Use automatic tight bounds.
>>> origin, maxpos = t.origin_and_maxpos(img)
>>> # Force a specific output size from origin 0.
>>> origin, maxpos = t.origin_and_maxpos(img, output_size=(80, 256, 256))
>>> # Force explicit coordinate bounds.
>>> origin, maxpos = t.origin_and_maxpos(
...     img,
...     output_size=((10, 90), (20, 220), (30, 230)),
...     force_size=True,
... )
transform_image(img, output_size=None, labels=None, force_size=True)[source]

Transform an image

output_size controls the output coordinate box. If it is None, the transformed image uses a tight bounding box based on transformed corners (and point targets for point-based transforms). If it is explicit, it can be either (z, y, x) max bounds from origin 0, or full per-axis bounds ((zmin, zmax), (ymin, ymax), (xmin, xmax)). With force_size=True these bounds are used exactly; with force_size=False they are treated as limits and the method may return a smaller box when possible.

Parameters:
  • img (numpy.ndarray or ndarray_shifted) – Input image. 2D images are promoted to 3D single-slice volumes.

  • output_size (None, sequence, or sequence of 2-tuples, optional) – Output bounds, same formats as origin_and_maxpos.

  • labels (bool or None, optional) – Label mode.

    • True: nearest-neighbor interpolation.

    • False: linear interpolation.

    • None: auto-detect with image_is_label.

  • force_size (bool, optional) – If False, output size may be smaller than output_size if the output would include empty space

Returns:

Transformed image in output coordinates.

Return type:

ndarray_shifted or numpy.ndarray

Notes

Generic implementation for non-rigid transforms. Subclasses can override with faster special cases.

Examples

>>> # Transform with automatic tight output bounds.
>>> out = t.transform_image(img)
>>> # Transform a label volume with nearest-neighbor interpolation.
>>> out = t.transform_image(labels_img, labels=True)
>>> # Transform with explicit output bounds.
>>> out = t.transform_image(
...     img,
...     output_size=((10, 90), (20, 220), (30, 230)),
... )
static pretransform(*args, **kwargs)[source]

Return the fixed pre-transform applied before this transform.

Returns:

Pre-transform to apply first. The default is Identity().

Return type:

Transform

Notes

Most transform classes should keep this default. Override it when a class represents a composed transform where only part of the chain is meant to be fit from data (for example, when an earlier component is fixed and only the final component is fit).

class castalign.base.PointTransform(points_start=None, points_end=None, **kwargs)[source]

Bases: Transform

Base class for transforms fit from point correspondences.

This class stores matched 3D points and is the base for transforms that are learned from those matches.

Notes

Subclasses can rely on:

  • self.points_start: source coordinates.

  • self.points_end: target coordinates.

Subclasses are expected to implement the standard transform behavior:

  • forward mapping through _transform,

  • inverse mapping through invert,

  • and optional fitting logic in _fit.

class castalign.base.AffineTransform[source]

Bases: object

Mixin implementing affine transform behavior.

This class provides shared affine logic for transform classes that represent mappings of the form: output = input @ matrix - shift.

Notes

Subclasses should use _fit to set:

  • self.matrix with shape (3, 3)

  • self.shift with shape (3,)

This mixin is designed for multiple inheritance with Transform or PointTransform-derived classes.

class castalign.base.PointTransformNoAnalyticInverse(*args, **kwargs)[source]

Bases: PointTransform

Base class for point transforms without an analytic inverse.

This class uses numerical inversion when needed, for transforms that are still bijective but do not have a closed-form inverse.

Notes

Subclasses should:

  • include {"invert": False} in DEFAULT_PARAMETERS

  • implement _transform(points, points_start, points_end)

By default, this class treats _transform as the inverse-direction map, which is typically the faster direction for image resampling workflows. Passing invert=False flips that behavior.

Parametric transforms

class castalign.base.RigidParametric(**kwargs)[source]

Bases: AffineTransform, Transform

Rigid transform defined by fixed translation and rotation parameters.

Parameters:
  • z, y, x (float, optional) – Translation offsets in voxel coordinates.

  • zrotate, yrotate, xrotate (float, optional) – Clockwise rotation angles (degrees) about each axis.

  • invert (bool, optional) – If True, uses the inverse rotation direction.

class castalign.base.AffineParametric(**kwargs)[source]

Bases: AffineTransform, Transform

Affine transform defined by fixed translation/rotation/scale/shear.

Parameters:
  • z, y, x (float, optional) – Translation offsets in voxel coordinates.

  • zrotate, yrotate, xrotate (float, optional) – Clockwise rotation angles (degrees) about each axis.

  • zscale, yscale, xscale (float, optional) – Axis-wise scale factors.

  • yzshear, xzshear, xyshear (float, optional) – Shear coefficients.

  • invert (bool, optional) – If True, inverts the combined affine matrix.

class castalign.base.MatrixParametric(**kwargs)[source]

Bases: AffineTransform, Transform

Affine transform specified directly by matrix coefficients.

Parameters:
  • a11, a12, a13, a21, a22, a23, a31, a32, a33 (float, optional) – Entries of the 3x3 affine matrix in row-major order.

  • z, y, x (float, optional) – Translation offsets in voxel coordinates.

class castalign.base.FlipParametric(**kwargs)[source]

Bases: AffineTransform, Transform

Axis-flip transform controlled by boolean flip parameters.

Parameters:
  • z, y, x (bool, optional) – Whether to flip along each axis.

  • zthickness, ythickness, xthickness (float or int, optional) – Axis extents used to compute the post-flip shift.

class castalign.base.RescaleParametric(**kwargs)[source]

Bases: AffineTransform, Transform

Axis-wise rescaling transform with fixed scale parameters.

Parameters:

z, y, x (float, optional) – Scale factors for each axis.

class castalign.base.TranslateParametric(**kwargs)[source]

Bases: AffineTransform, Transform

Translation-only transform with fixed z/y/x offsets.

Parameters:

z, y, x (float, optional) – Translation offsets in voxel coordinates.

Point-based transforms

class castalign.base.Identity(**kwargs)[source]

Bases: AffineTransform, Transform

Identity transform that leaves coordinates unchanged.

class castalign.base.Translate(points_start=None, points_end=None, **kwargs)[source]

Bases: AffineTransform, PointTransform

Translation-only transform fit from corresponding points.

class castalign.base.Rigid(points_start=None, points_end=None, **kwargs)[source]

Bases: AffineTransform, PointTransform

Rigid transform fit from points using rotation and translation.

class castalign.base.Affine(points_start=None, points_end=None, **kwargs)[source]

Bases: AffineTransform, PointTransform

Full affine transform fit from corresponding 3D points.

class castalign.base.LaminarAffine(points_start=None, points_end=None, **kwargs)[source]

Bases: AffineTransform, PointTransform

Laminar affine fit for section-like data.

Splits fitting into high-variance laminar components plus low-variance normal-depth component to reduce skew in thin volumes. The laminar basis is estimated from the dominant fitted plane of the matched points.

class castalign.base.Triangulation(points_start=None, points_end=None, **kwargs)[source]

Bases: PointTransform

Nonlinear 3D deformation using piecewise-affine triangulation.

This transform warps a 3D volume by building a Delaunay triangulation over control points, then applying a local affine map per tetrahedron.

Notes

The implementation supports both directions of mapping. For one direction it can use find_simplex directly; for the other it manually checks tetrahedron containment, because SciPy does not provide the exact arbitrary-triangulation path needed for this workflow.

class castalign.base.LaminarTriangulation(points_start=None, points_end=None, **kwargs)[source]

Bases: PointTransform

Nonlinear laminar triangulation in 3D.

This is generally the recommended nonlinear transform for mostly flat section-like 3D data (broad in two dimensions, thinner in the third).

If normal_z, normal_y, and normal_x are all zero, the normal is estimated automatically from the input points.

Notes

The transform triangulates points after projection into the fitted laminar plane, then computes local 3D affine maps using those projected triangles plus a normal-direction anchor so depth is handled consistently.

As with Triangulation, one mapping direction can use find_simplex directly, while the other uses manual triangle containment checks due to SciPy API limitations for this specific inverse workflow.

Deprecated transforms

class castalign.base.Flip(**kwargs)[source]

Bases: AffineTransform, Transform

Deprecated parametric axis-flip transform.

class castalign.base.DistanceWeightedAverageGaussian(*args, **kwargs)[source]

Bases: PointTransformNoAnalyticInverse

Deprecated nonlinear displacement-field transform with Gaussian weighting.