Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoadImageD and MetaTensor #5509

Closed
myron opened this issue Nov 10, 2022 · 5 comments · Fixed by #5916
Closed

LoadImageD and MetaTensor #5509

myron opened this issue Nov 10, 2022 · 5 comments · Fixed by #5916

Comments

@myron
Copy link
Collaborator

myron commented Nov 10, 2022

It's more of question to clarify, not a bug. can you help clarify plz

  • LoadImage() and LoadImaged() always return MetaTensor. Is it by design? I'm okay either way, just want to clarify. So we can't return the original data format ?

  • line 281 return img, img.meta if isinstance(img, MetaTensor) else meta_data. The img seems to be always a MetaTensor, is that check necessary?

meta_data[Key.FILENAME_OR_OBJ] = f"{ensure_tuple(filename)[0]}" # Path obj should be strings for data loader
img = MetaTensor.ensure_torch_and_prune_meta(
img_array, meta_data, self.simple_keys, pattern=self.pattern, sep=self.sep
)
if self.ensure_channel_first:
img = EnsureChannelFirst()(img)
if self.image_only:
return img
return img, img.meta if isinstance(img, MetaTensor) else meta_data

  • inside of MetaTensor.ensure_torch_and_prune_meta(), we seems to do conversion to Tensor twice on lines 487 and 504. on 487 we img = convert_to_tensor(im) and return MetaTensor(img, meta=meta) will internally call torch.as_tensor on img.

img = convert_to_tensor(im) # potentially ascontiguousarray
# if not tracking metadata, return `torch.Tensor`
if not get_track_meta() or meta is None:
return img
# remove any superfluous metadata.
if simple_keys:
# ensure affine is of type `torch.Tensor`
if MetaKeys.AFFINE in meta:
meta[MetaKeys.AFFINE] = convert_to_tensor(meta[MetaKeys.AFFINE]) # bc-breaking
remove_extra_metadata(meta) # bc-breaking
if pattern is not None:
meta = monai.transforms.DeleteItemsd(keys=pattern, sep=sep, use_re=True)(meta)
# return the `MetaTensor`
return MetaTensor(img, meta=meta)

Thank you

@wyli
Copy link
Contributor

wyli commented Nov 10, 2022

it's possible to globally turn off the metatensor...

>>> from monai.data import set_track_meta
>>> set_track_meta(False)
>>> from monai.transforms import LoadImage
>>> x = LoadImage(image_only=True)("IBSR_01_ana.nii.gz")
>>> type(x)
<class 'torch.Tensor'>

but these are not systematically tested for end-to-end workflows, for example, some transform inverting pipelines might not work properly...

@myron
Copy link
Collaborator Author

myron commented Nov 10, 2022

it's possible to globally turn off the metatensor...

>>> from monai.data import set_track_meta
>>> set_track_meta(False)
>>> from monai.transforms import LoadImage
>>> x = LoadImage(image_only=True)("IBSR_01_ana.nii.gz")
>>> type(x)
<class 'torch.Tensor'>

but these are not systematically tested for end-to-end workflows, for example, some transform inverting pipelines might not work properly...

I see, thank you. what about the last question: lines 487 and 504 seems both convert to tensor internally, or can we remove line 487 img = convert_to_tensor(im) ?

@wyli
Copy link
Contributor

wyli commented Nov 10, 2022

I think it is about returning a fresh copy of the input, @rijobro perhaps can confirm

@rijobro
Copy link
Contributor

rijobro commented Nov 14, 2022

Looking at the code, I'm not 100% sure if both are needed. I'm also not 100% which of them would create a deepcopy of the data. Feel free to mess around with it for a variety of inputs (torch.Tensor, MetaTensor and np.ndarray) and see how many copies are created (when debugging, you could do print(img is im) etc.). Also check for contiguous vs non-contiguous input, as the comment mentions this: img = convert_to_tensor(im) # potentially ascontiguousarray.

If they can be combined into one, I'm happy for us to do that.

wyli added a commit to wyli/MONAI that referenced this issue Jan 30, 2023
Signed-off-by: Wenqi Li <wenqil@nvidia.com>
wyli added a commit to wyli/MONAI that referenced this issue Jan 30, 2023
Signed-off-by: Wenqi Li <wenqil@nvidia.com>
@wyli wyli closed this as completed in #5916 Feb 1, 2023
@wyli wyli closed this as completed in b592164 Feb 1, 2023
@wyli
Copy link
Contributor

wyli commented Feb 1, 2023

thanks, now the repeated convert_to_tensor is changed to a simple meta assignment:

# return the `MetaTensor`
if meta is None:
meta = {}
img.meta = meta
if MetaKeys.AFFINE in meta:
img.affine = meta[MetaKeys.AFFINE] # this uses the affine property setter
else:
img.affine = MetaTensor.get_default_affine()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants