Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions monai/deploy/operators/dicom_series_to_volume_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class DICOMSeriesToVolumeOperator(Operator):
image: Image object.
"""

# Use constants instead of enums in monai to avoid dependency at this level.
MONAI_UTIL_ENUMS_SPACEKEYS_LPS = "LPS"
MONAI_TRANSFORMS_SPATIAL_METADATA_NAME = "space"
METADATA_SPACE_LPS = {MONAI_TRANSFORMS_SPATIAL_METADATA_NAME: MONAI_UTIL_ENUMS_SPACEKEYS_LPS}

def __init__(self, fragment: Fragment, *args, **kwargs):
"""Create an instance for a containing application object.

Expand Down Expand Up @@ -84,6 +89,18 @@ def convert_to_image(self, study_selected_series_list: List[StudySelectedSeries]
metadata.update(self._get_instance_properties(study_selected_series.study))
selection_metadata = {"selection_name": selection_name}
metadata.update(selection_metadata)
# Add the metadata to specify LPS.
# Previously, this was set in ImageReader class, but moving it here allows other loaders
# to determine this value on its own, e.g. NIfTI loader but it does not set this
# resulting in the MONAI Orientation transform to default the labels to RAS.
# It is assumed that the ImageOrientationPatient will be set accordingly if the
# PatientPosition is other than HFS.
# NOTE: This value is properly parsed by MONAI Orientation transform from v1.5.1 onwards.
# Some early MONAI model inference configs incorrectly specify orientation to RAS
# due part to previous MONAI versions did not correctly parse this metadata from
# the input MetaTensor and defaulting to RAS. Now with LPS properly set, the inference
# configs then need to be updated to specify LPS, to achieve the same result.
metadata.update(self.METADATA_SPACE_LPS)

voxel_data = self.generate_voxel_data(dicom_series)
image = self.create_volumetric_image(voxel_data, metadata)
Expand Down
6 changes: 4 additions & 2 deletions monai/deploy/operators/monai_bundle_inference_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ def _init_config(self, config_names):
)

def _get_compose(self, obj_name, disallowed_prefixes):
"""Gets a Compose object containing a sequence fo transforms from item `obj_name` in `self._parser`."""
"""Gets a Compose object containing a sequence of transforms from item `obj_name` in `self._parser`."""

if self._parser.get(obj_name) is not None:
compose = self._parser.get_parsed_content(obj_name)
Expand Down Expand Up @@ -749,6 +749,7 @@ def compute(self, op_input, op_output, context):
raise ValueError("`meta_data` must be a dict.")
value = MetaTensor.ensure_torch_and_prune_meta(value, meta_data)
inputs[name] = value
logging.debug(f"Input MetaTensor metadata 'space': {value.meta.get('space', None)}")
# Named metadata dict not needed any more, as it is in the MetaTensor

inputs = self.pre_process(inputs)
Expand Down Expand Up @@ -1062,7 +1063,8 @@ def _convert_from_image_dicom_source(self, img: Image) -> Tuple[np.ndarray, Dict
# Use defines MetaKeys directly
meta_dict[MetaKeys.ORIGINAL_AFFINE] = np.asarray(img_meta_dict.get("nifti_affine_transform", None))
meta_dict[MetaKeys.AFFINE] = meta_dict[MetaKeys.ORIGINAL_AFFINE].copy()
meta_dict[MetaKeys.SPACE] = SpaceKeys.LPS # not using SpaceKeys.RAS or affine_lps_to_ras
# Disabled setting the SPACE key below as it has changed to be set in the actual loader implementation.
# meta_dict[MetaKeys.SPACE] = SpaceKeys.LPS # not using SpaceKeys.RAS or affine_lps_to_ras

# Similarly the Image ndarray has dim order DHW, to be rearranged to WHD.
# TODO: Need to revisit this once multi-channel image is supported and the Image class itself
Expand Down
5 changes: 3 additions & 2 deletions monai/deploy/operators/monai_seg_inference_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def filter_sw_kwargs(**kwargs) -> Tuple[Dict[str, Any], Dict[str, Any]]:
- Are not explicitly defined in the __init__ of this class
- Are not explicitly used when calling sliding_window_inference

2. A dicionary of named parameters to pass to the base class __init__ of this class that:
2. A dictionary of named parameters to pass to the base class __init__ of this class that:
- Are not used when calling sliding_window_inference
- Can be successfully converted from Python --> Holoscan's C++ layer

Expand Down Expand Up @@ -582,7 +582,8 @@ def _get_meta_dict(self, img: Image) -> Dict:
# Use define metadata kyes directly
meta_dict[MetaKeys.ORIGINAL_AFFINE] = np.asarray(img_meta_dict.get("nifti_affine_transform", None))
meta_dict[MetaKeys.AFFINE] = meta_dict[MetaKeys.ORIGINAL_AFFINE].copy()
meta_dict[MetaKeys.SPACE] = SpaceKeys.LPS # not using SpaceKeys.RAS or affine_lps_to_ras
# Disabled setting the SPACE key below as it has changed to be set in the actual loader implementation.
# meta_dict[MetaKeys.SPACE] = SpaceKeys.LPS # not using SpaceKeys.RAS or affine_lps_to_ras
# The spatial shape, again, referring to ITKReader, it is the WHD
meta_dict[MetaKeys.SPATIAL_SHAPE] = np.asarray(img.asnumpy().T.shape)
# Well, no channel as the image data shape is forced to the the same as spatial shape
Expand Down
Loading