Skip to content

Pad

Pad

Bases: SpatialTransform

Add a border of voxels to each side of the volume.

Parameters:

Name Type Description Default
padding PaddingParam

Tuple \((i_\text{ini}, i_\text{fin}, j_\text{ini}, j_\text{fin}, k_\text{ini}, k_\text{fin})\) defining the number of voxels added to the edges of each axis. If the initial shape of the image is \(I \times J \times K\), the final shape will be \((I + i_\text{ini} + i_\text{fin}) \times (J + j_\text{ini} + j_\text{fin}) \times (K + k_\text{ini} + k_\text{fin})\). If only three values \((i, j, k)\) are provided, then \(i_\text{ini} = i_\text{fin} = i\), etc. If only one value \(n\) is provided, all six values are \(n\).

required
padding_mode PaddingMode

One of 'constant', 'reflect', 'replicate', 'circular', 'mean', 'median', or 'minimum'. Statistical modes use one value computed from the whole image volume. For integer inputs, 'mean' and 'median' may be truncated to the input dtype and emit a warning.

'constant'
fill float

Fill value when padding_mode='constant'.

0
**kwargs Any

See Transform for additional keyword arguments.

{}

Examples:

>>> import torchio as tio
>>> transform = tio.Pad(padding=10)
>>> transform = tio.Pad(padding=(5, 10, 0))
>>> transform = tio.Pad(padding=10, padding_mode='reflect')
>>> transform = tio.Pad(padding=10, padding_mode='minimum')
Source code in src/torchio/transforms/spatial/pad.py
class Pad(SpatialTransform):
    r"""Add a border of voxels to each side of the volume.

    Args:
        padding: Tuple
            $(i_\text{ini}, i_\text{fin}, j_\text{ini}, j_\text{fin},
            k_\text{ini}, k_\text{fin})$
            defining the number of voxels added to the edges of
            each axis. If the initial shape of the image is
            $I \times J \times K$, the final shape will be
            $(I + i_\text{ini} + i_\text{fin}) \times
            (J + j_\text{ini} + j_\text{fin}) \times
            (K + k_\text{ini} + k_\text{fin})$.
            If only three values $(i, j, k)$ are provided, then
            $i_\text{ini} = i_\text{fin} = i$, etc.
            If only one value $n$ is provided, all six values are $n$.
        padding_mode: One of `'constant'`, `'reflect'`,
            `'replicate'`, `'circular'`, `'mean'`, `'median'`, or
            `'minimum'`. Statistical modes use one value computed from
            the whole image volume. For integer inputs, `'mean'` and
            `'median'` may be truncated to the input dtype and emit a
            warning.
        fill: Fill value when `padding_mode='constant'`.
        **kwargs: See [`Transform`][torchio.Transform] for additional
            keyword arguments.

    Examples:
        >>> import torchio as tio
        >>> transform = tio.Pad(padding=10)
        >>> transform = tio.Pad(padding=(5, 10, 0))
        >>> transform = tio.Pad(padding=10, padding_mode='reflect')
        >>> transform = tio.Pad(padding=10, padding_mode='minimum')
    """

    def __init__(
        self,
        *,
        padding: PaddingParam,
        padding_mode: PaddingMode = "constant",
        fill: float = 0,
        **kwargs: Any,
    ) -> None:
        super().__init__(**kwargs)
        self.padding = _parse_padding(padding)
        self.padding_mode = parse_padding_mode(padding_mode)
        self.fill = fill

    def make_params(self, batch: SubjectsBatch) -> dict[str, Any]:
        return {
            "padding": self.padding,
            "padding_mode": self.padding_mode,
            "fill": self.fill,
        }

    def apply_transform(
        self,
        batch: SubjectsBatch,
        params: dict[str, Any],
    ) -> SubjectsBatch:
        i0, i1, j0, j1, k0, k1 = params["padding"]
        mode = params["padding_mode"]
        fill = params["fill"]
        for _name, img_batch in self._get_images(batch).items():
            img_batch.data = pad_tensor(
                img_batch.data,
                (i0, i1, j0, j1, k0, k1),
                mode,
                fill,
            )
            # Update each affine's origin (shift back)
            for affine in img_batch.affines:
                origin_shift = affine.data[:3, :3] @ affine.data.new_tensor(
                    [-float(i0), -float(j0), -float(k0)],
                )
                affine._matrix[:3, 3] += origin_shift
        return batch

    @property
    def invertible(self) -> bool:
        return True

    def inverse(self, params: dict[str, Any]) -> Any:
        """Inverse of Pad is Crop."""
        from .crop import Crop

        return Crop(cropping=params["padding"], copy=False)

supports_per_instance_params property

Whether this transform can sample parameters per batch element.

Defaults to False. Transforms that implement per-instance parameter sampling override this to return True. When False, the transform always uses batch-shared parameters regardless of the per_instance flag, preserving the legacy behavior.

supports_per_instance_p property

Whether this transform can gate each batch element independently.

Defaults to False. Shape-preserving transforms that implement per-element probability override this to return True. Shape-changing transforms must leave it False because masked and unmasked elements would have incompatible shapes.

forward(data)

forward(data: Subject) -> Subject
forward(data: Image) -> Image
forward(data: Tensor) -> Tensor
forward(data: np.ndarray) -> np.ndarray
forward(data: sitk.Image) -> sitk.Image
forward(data: nib.Nifti1Image) -> nib.Nifti1Image
forward(data: dict) -> dict
forward(data: ImagesBatch) -> ImagesBatch
forward(data: SubjectsBatch) -> SubjectsBatch

Apply the transform.

The output type always matches the input type.

Parameters:

Name Type Description Default
data Any

Input data to transform.

required
Source code in src/torchio/transforms/transform.py
def forward(self, data: Any) -> Any:
    """Apply the transform.

    The output type always matches the input type.

    Args:
        data: Input data to transform.
    """
    return self._execute(data, params=None, sample_params=True)

apply_with_params(data, params)

apply_with_params(data: Subject, params: dict[str, Any]) -> Subject
apply_with_params(data: Image, params: dict[str, Any]) -> Image
apply_with_params(data: Tensor, params: dict[str, Any]) -> Tensor
apply_with_params(data: np.ndarray, params: dict[str, Any]) -> np.ndarray
apply_with_params(data: sitk.Image, params: dict[str, Any]) -> sitk.Image
apply_with_params(data: nib.Nifti1Image, params: dict[str, Any]) -> nib.Nifti1Image
apply_with_params(data: dict, params: dict[str, Any]) -> dict
apply_with_params(data: ImagesBatch, params: dict[str, Any]) -> ImagesBatch
apply_with_params(data: SubjectsBatch, params: dict[str, Any]) -> SubjectsBatch

Apply an exact parameter set without sampling.

This method bypasses the transform probability and make_params(), but otherwise follows the normal transform lifecycle: copy handling, input wrapping, output-type restoration, and history recording.

Parameters:

Name Type Description Default
data Any

Input data to transform.

required
params dict[str, Any]

Exact parameters accepted by apply_transform.

required

Returns:

Type Description
Any

Transformed data with the same type as the input.

Raises:

Type Description
TypeError

If params is not a dictionary.

NotImplementedError

If the transform does not expose one exact-parameter kernel.

ValueError

If per-instance parameter dimensions do not match the input batch.

Source code in src/torchio/transforms/transform.py
def apply_with_params(
    self,
    data: Any,
    params: dict[str, Any],
) -> Any:
    """Apply an exact parameter set without sampling.

    This method bypasses the transform probability and
    [`make_params()`][torchio.Transform.make_params], but otherwise
    follows the normal transform lifecycle: copy handling, input
    wrapping, output-type restoration, and history recording.

    Args:
        data: Input data to transform.
        params: Exact parameters accepted by `apply_transform`.

    Returns:
        Transformed data with the same type as the input.

    Raises:
        TypeError: If `params` is not a dictionary.
        NotImplementedError: If the transform does not expose one
            exact-parameter kernel.
        ValueError: If per-instance parameter dimensions do not
            match the input batch.
    """
    if not self._supports_apply_with_params:
        msg = (
            f"{type(self).__name__}.apply_with_params() is not supported"
            " because this transform does not expose a single"
            " make_params/apply_transform parameter kernel."
        )
        raise NotImplementedError(msg)
    if not isinstance(params, dict):
        msg = f"Expected params to be a dict, got {type(params).__name__}"
        raise TypeError(msg)
    return self._execute(
        data,
        params=_copy.deepcopy(params),
        sample_params=False,
    )

to_hydra()

Export as a Hydra-compatible config dict.

Returns a dict with _target_ set to the fully qualified class name and only non-default field values included.

Returns:

Type Description
dict[str, Any]

Dict suitable for hydra.utils.instantiate().

Source code in src/torchio/transforms/transform.py
def to_hydra(self) -> dict[str, Any]:
    """Export as a Hydra-compatible config dict.

    Returns a dict with `_target_` set to the fully qualified
    class name and only non-default field values included.

    Returns:
        Dict suitable for `hydra.utils.instantiate()`.
    """
    from .parameter_range import _ParameterRange

    cls = type(self)
    target = f"torchio.{cls.__qualname__}"
    cfg: dict[str, Any] = {"_target_": target}

    for name, default in _collect_init_params(cls).items():
        value = getattr(self, name, default)
        if isinstance(value, _ParameterRange):
            if value._original == default:
                continue
            value = _hydra_value(value._original)
        elif value == default:
            continue
        else:
            value = _hydra_value(value)
        cfg[name] = value
    return cfg

inverse(params)

Inverse of Pad is Crop.

Source code in src/torchio/transforms/spatial/pad.py
def inverse(self, params: dict[str, Any]) -> Any:
    """Inverse of Pad is Crop."""
    from .crop import Crop

    return Crop(cropping=params["padding"], copy=False)