Skip to content

Compose

Bases: Transform

Compose several transforms together.

The input is deep-copied once before the pipeline runs (by default), then each transform operates in-place on the copy. This avoids redundant copies when chaining many transforms.

Parameters:

Name Type Description Default
transforms Sequence[Transform] | Mapping[str, Transform] | None

Sequence of transforms to apply sequentially, or a mapping whose values are the transforms (keys are used as human-readable names and ignored at runtime).

None
copy bool

If True (default), deep-copy the input before applying the pipeline. Set to False when this Compose is nested inside another Compose.

True
**kwargs Any

See Transform for additional keyword arguments.

{}

Examples:

>>> import torchio as tio
>>> preprocessing = tio.Compose([
...     tio.Flip(axes=(0,), p=0.5),
...     tio.Noise(std=(0.01, 0.1)),
... ])
>>> augmented = preprocessing(subject)
>>> named = tio.Compose({
...     "flip": tio.Flip(axes=(0,), p=0.5),
...     "noise": tio.Noise(std=(0.01, 0.1)),
... })
Source code in src/torchio/transforms/compose.py
class Compose(Transform):
    """Compose several transforms together.

    The input is deep-copied once before the pipeline runs (by
    default), then each transform operates in-place on the copy.
    This avoids redundant copies when chaining many transforms.

    Args:
        transforms: Sequence of transforms to apply sequentially, or a
            mapping whose values are the transforms (keys are used as
            human-readable names and ignored at runtime).
        copy: If `True` (default), deep-copy the input before
            applying the pipeline. Set to `False` when this
            `Compose` is nested inside another `Compose`.
        **kwargs: See [`Transform`][torchio.Transform] for additional
            keyword arguments.

    Examples:
        >>> import torchio as tio
        >>> preprocessing = tio.Compose([
        ...     tio.Flip(axes=(0,), p=0.5),
        ...     tio.Noise(std=(0.01, 0.1)),
        ... ])
        >>> augmented = preprocessing(subject)
        >>> named = tio.Compose({
        ...     "flip": tio.Flip(axes=(0,), p=0.5),
        ...     "noise": tio.Noise(std=(0.01, 0.1)),
        ... })
    """

    def __init__(
        self,
        transforms: Sequence[Transform] | Mapping[str, Transform] | None = None,
        *,
        copy: bool = True,
        **kwargs: Any,
    ) -> None:
        super().__init__(copy=copy, **kwargs)
        if transforms is None:
            self.transforms: list[Transform] = []
        elif isinstance(transforms, Mapping):
            mapping = cast(Mapping[str, Transform], transforms)
            self.transforms = list(mapping.values())
        else:
            self.transforms = list(transforms)

    def forward(self, data):
        if self.copy:
            data = copy.deepcopy(data)
        subject, unwrap = self._wrap(data)
        for transform in self.transforms:
            old_copy = transform.copy
            transform.copy = False
            subject = transform(subject)
            transform.copy = old_copy
        return unwrap(subject)

    def to_hydra(self) -> dict[str, Any]:
        cfg = super().to_hydra()
        cfg["transforms"] = [t.to_hydra() for t in self.transforms]
        return cfg

invertible property

Whether this transform can be inverted.

make_params(batch)

Sample random parameters for this transform.

Override in subclasses that have random behavior.

Parameters:

Name Type Description Default
batch SubjectsBatch

A SubjectsBatch.

required

Returns:

Type Description
dict[str, Any]

Dict of sampled parameters.

Source code in src/torchio/transforms/transform.py
def make_params(self, batch: SubjectsBatch) -> dict[str, Any]:
    """Sample random parameters for this transform.

    Override in subclasses that have random behavior.

    Args:
        batch: A `SubjectsBatch`.

    Returns:
        Dict of sampled parameters.
    """
    return {}

apply_transform(batch, params)

Apply the transform with the given parameters.

Must be overridden by subclasses. Receives a SubjectsBatch whose ImagesBatch entries contain 5D tensors (B, C, I, J, K). Use negative indexing (-3, -2, -1) for spatial dims.

Parameters:

Name Type Description Default
batch SubjectsBatch

A SubjectsBatch to transform.

required
params dict[str, Any]

Parameters from make_params.

required

Returns:

Type Description
SubjectsBatch

Transformed SubjectsBatch.

Source code in src/torchio/transforms/transform.py
def apply_transform(
    self,
    batch: SubjectsBatch,
    params: dict[str, Any],
) -> SubjectsBatch:
    """Apply the transform with the given parameters.

    Must be overridden by subclasses. Receives a `SubjectsBatch`
    whose `ImagesBatch` entries contain 5D tensors
    `(B, C, I, J, K)`. Use negative indexing (`-3`, `-2`,
    `-1`) for spatial dims.

    Args:
        batch: A `SubjectsBatch` to transform.
        params: Parameters from `make_params`.

    Returns:
        Transformed `SubjectsBatch`.
    """
    raise NotImplementedError

inverse(params)

Return a transform that undoes this one.

Override in invertible subclasses. The returned transform, when applied, reverses the effect of the forward pass with the given parameters.

Parameters:

Name Type Description Default
params dict[str, Any]

The parameters recorded in the forward pass.

required

Returns:

Type Description
Transform

A new Transform instance that inverts this one.

Source code in src/torchio/transforms/transform.py
def inverse(self, params: dict[str, Any]) -> Transform:
    """Return a transform that undoes this one.

    Override in invertible subclasses. The returned transform,
    when applied, reverses the effect of the forward pass with
    the given parameters.

    Args:
        params: The parameters recorded in the forward pass.

    Returns:
        A new `Transform` instance that inverts this one.
    """
    msg = f"{type(self).__name__} is not invertible"
    raise NotImplementedError(msg)