Skip to content

Commit

Permalink
Fixes #6840
Browse files Browse the repository at this point in the history
According to the issue, this PR addresses on the meta dictionary `data['pixdim']` of NIfTI images does not update after applying the `spacing` or `spacingd`.
To align with `affine`, we update `data['pixdim']` and keep the original metainfo in `data['original_pixdim']`.
Additionally, this PR also update the metainfo `key_{meta_key_postfix}['pixdim']` in NIfTI images, consistent with `spaced_data_dict['image_meta_dict']['pixdim']` in issue #6832.

Signed-off-by: Wei_Chuan, Chiang <[email protected]>
Co-authored-by: einsyang723 <[email protected]>
Co-authored-by: IamTingTing <[email protected]>
  • Loading branch information
3 people committed Dec 23, 2024
1 parent d36f0c8 commit cdb8391
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 0 deletions.
2 changes: 2 additions & 0 deletions monai/data/image_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,8 @@ def get_data(self, img) -> tuple[np.ndarray, dict]:

for i, filename in zip(ensure_tuple(img), self.filenames):
header = self._get_meta_dict(i)
if MetaKeys.PIXDIM in header:
header[MetaKeys.ORIGINAL_PIXDIM] = np.array(header[MetaKeys.PIXDIM], copy=True)
header[MetaKeys.AFFINE] = self._get_affine(i)
header[MetaKeys.ORIGINAL_AFFINE] = self._get_affine(i)
header["as_closest_canonical"] = self.as_closest_canonical
Expand Down
4 changes: 4 additions & 0 deletions monai/data/meta_tensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,10 @@ def pixdim(self):
return [affine_to_spacing(a) for a in self.affine]
return affine_to_spacing(self.affine)

def set_pixdim(self) -> None:
"""Update pixdim based on current affine."""
self.meta[MetaKeys.PIXDIM][1 : 1 + len(self.pixdim)] = affine_to_spacing(self.affine)

def peek_pending_shape(self):
"""
Get the currently expected spatial shape as if all the pending operations are executed.
Expand Down
3 changes: 3 additions & 0 deletions monai/transforms/spatial/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ def __call__(
dtype=dtype,
lazy=lazy_,
)
if isinstance(data_array, MetaTensor) and "pixdim" in data_array.meta:
data_array = 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.")
Expand Down
5 changes: 5 additions & 0 deletions monai/transforms/spatial/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
import numpy as np
import torch

import monai.transforms as transforms
from monai.config import DtypeLike, KeysCollection, SequenceStr
from monai.config.type_definitions import NdarrayOrTensor
from monai.data.box_utils import BoxMode, StandardMode
from monai.data.meta_obj import get_track_meta
from monai.data.meta_tensor import MetaTensor
from monai.data.utils import is_supported_format
from monai.networks.layers.simplelayers import GaussianFilter
from monai.transforms.croppad.array import CenterSpatialCrop
from monai.transforms.inverse import InvertibleTransform
Expand Down Expand Up @@ -520,6 +522,9 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor], lazy: bool | None = No
output_spatial_shape=output_shape_k if should_match else None,
lazy=lazy_,
)
if isinstance(d[key], MetaTensor) and "filename_or_obj" in d[key].meta:
if is_supported_format(d[key].meta["filename_or_obj"], ["nii", "nii.gz"]):
d = transforms.sync_meta_info(key, d)
if output_shape_k is None:
output_shape_k = d[key].peek_pending_shape() if isinstance(d[key], MetaTensor) else d[key].shape[1:]
return d
Expand Down
2 changes: 2 additions & 0 deletions monai/utils/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ class MetaKeys(StrEnum):
Typical keys for MetaObj.meta
"""

PIXDIM = "pixdim" # MetaTensor.pixdim
ORIGINAL_PIXDIM = "original_pixdim" # the pixdim after image loading before any data processing
AFFINE = "affine" # MetaTensor.affine
ORIGINAL_AFFINE = "original_affine" # the affine after image loading before any data processing
SPATIAL_SHAPE = "spatial_shape" # optional key for the length in each spatial dimension
Expand Down

0 comments on commit cdb8391

Please sign in to comment.