Repository: Project-MONAI/MONAI
File: monai/transforms/spatial/array.py (Python)

Code before:
            out_d[idx] = _d if (mn - AFFINE_TOL) <= _d <= (mx + AFFINE_TOL) else target

        if not align_corners and scale_extent:
            warnings.warn("align_corners=False is not compatible with scale_extent=True.")

        # compute output affine, shape and offset
        new_affine = zoom_affine(affine_, out_d, diagonal=self.diagonal)
        scale_extent = self.scale_extent if scale_extent is None else scale_extent
        output_shape, offset = compute_shape_offset(original_spatial_shape, affine_, new_affine, scale_extent)
        new_affine[:sr, -1] = offset[:sr]

        actual_shape = list(output_shape) if output_spatial_shape is None else output_spatial_shape
        lazy_ = self.lazy if lazy is None else lazy
        data_array = self.sp_resample(
            data_array,
            dst_affine=torch.as_tensor(new_affine),
            spatial_size=actual_shape,  # type: ignore
            mode=mode,
            padding_mode=padding_mode,
            align_corners=align_corners,
            dtype=dtype,
            lazy=lazy_,
        )
        if isinstance(data_array, MetaTensor) and "pixdim" in data_array.meta:
            data_array = cast(MetaTensor, data_array.clone())
            data_array.set_pixdim()
        if self.recompute_affine and isinstance(data_array, MetaTensor):
            if lazy_:
                raise NotImplementedError("recompute_affine is not supported with lazy evaluation.")
            a = scale_affine(original_spatial_shape, actual_shape)
            data_array.affine = convert_to_dst_type(a, affine_)[0]  # type: ignore
        return data_array

    def inverse(self, data: torch.Tensor) -> torch.Tensor:
        return self.sp_resample.inverse(data)


class Orientation(InvertibleTransform, LazyTransform):
    """
    Change the input image's orientation into the specified based on `axcodes`.

    This transform is capable of lazy execution. See the :ref:`Lazy Resampling topic<lazy_resampling>`
    for more information.
    """

    backend = [TransformBackends.NUMPY, TransformBackends.TORCH]

    def __init__(
        self,
        axcodes: str | None = None,
        as_closest_canonical: bool = False,

Review comment (suggestion):
It seems that the pixel dimensions (pixdim) are only updated in the Spacing transformation. This is why I previously suggested that we should only retain the `original_pixdim`, as the latest pixdim can be derived from the metadata in the MetaTensor and the affine transformation.

Additionally, the use of `meta_dict` for logging metadata is becoming outdated. Perhaps we no longer need to maintain it? What are your thoughts on this?

```
import torch
from monai.transforms import Spacing

data = torch.randn(2, 1, 32, 32, 32)
trans = Spacing(pixdim=(1.5, 1.5, 1.0))
out = trans(data)
print(out.pixdim) -- > (1.5, 1.5, 1.0)
```
cc @ericspod @Nic-Ma 

Code after:
            if mn > mx:
                raise ValueError(f"min_pixdim is larger than max_pixdim at dim {idx}: min {mn} max {mx} out {target}.")
            out_d[idx] = _d if (mn - AFFINE_TOL) <= _d <= (mx + AFFINE_TOL) else target

        if not align_corners and scale_extent:
            warnings.warn("align_corners=False is not compatible with scale_extent=True.")

        # compute output affine, shape and offset
        new_affine = zoom_affine(affine_, out_d, diagonal=self.diagonal)
        scale_extent = self.scale_extent if scale_extent is None else scale_extent
        output_shape, offset = compute_shape_offset(original_spatial_shape, affine_, new_affine, scale_extent)
        new_affine[:sr, -1] = offset[:sr]

        actual_shape = list(output_shape) if output_spatial_shape is None else output_spatial_shape
        lazy_ = self.lazy if lazy is None else lazy
        data_array = self.sp_resample(
            data_array,
            dst_affine=torch.as_tensor(new_affine),
            spatial_size=actual_shape,  # type: ignore
            mode=mode,
            padding_mode=padding_mode,
            align_corners=align_corners,
            dtype=dtype,
            lazy=lazy_,
        )
        if self.recompute_affine and isinstance(data_array, MetaTensor):
            if lazy_:
                raise NotImplementedError("recompute_affine is not supported with lazy evaluation.")
            a = scale_affine(original_spatial_shape, actual_shape)
            data_array.affine = convert_to_dst_type(a, affine_)[0]  # type: ignore
        return data_array

    def inverse(self, data: torch.Tensor) -> torch.Tensor:
        return self.sp_resample.inverse(data)


class Orientation(InvertibleTransform, LazyTransform):
    """
    Change the input image's orientation into the specified based on `axcodes`.

    This transform is capable of lazy execution. See the :ref:`Lazy Resampling topic<lazy_resampling>`
    for more information.
    """

    backend = [TransformBackends.NUMPY, TransformBackends.TORCH]

    @deprecated_arg_default(
        name="labels",
        old_default=(("L", "R"), ("P", "A"), ("I", "S")),
        new_default=None,
        msg_suffix=(