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

itk_torch_bridge.metatensor_to_itk_image() incorrect orientation #6985

Closed
ibro45 opened this issue Sep 14, 2023 · 4 comments · Fixed by #7000
Closed

itk_torch_bridge.metatensor_to_itk_image() incorrect orientation #6985

ibro45 opened this issue Sep 14, 2023 · 4 comments · Fixed by #7000
Assignees
Labels
enhancement New feature or request

Comments

@ibro45
Copy link
Contributor

ibro45 commented Sep 14, 2023

Describe the bug
I have been trying to use itk_torch_bridge.metatensor_to_itk_image() to save the predicted masks, but it consistently fails to save them in the correct orientation. I initially suspected that something went wrong in the inverse transforms I was doing before saving, but I could not find any problem there. Finally, I looked into the metatensor_to_itk_image() itself.

Apparently, loading an image with MONAI, converting it to ITK, and then writing it will result in a different orientation, as can be seen in the Slicer screenshots below.

To Reproduce
Use any scan. For reproducibility, I used this one: https://github.com/google-deepmind/tcia-ct-scan-dataset/blob/master/nrrds/test/oncologist/0522c0017/CT_IMAGE.nrrd

import itk
from monai.data.itk_torch_bridge import metatensor_to_itk_image
from monai.transforms import Compose, LoadImaged, EnsureTyped, EnsureChannelFirstd

transforms = Compose(
        [
            LoadImaged(keys=["image"]),
            EnsureTyped(keys=["image"]),
            EnsureChannelFirstd(keys=["image"]),
        ]
    )

out = transforms({"image": "./CT_IMAGE.nrrd"})
image = out["image"]

itk_image = metatensor_to_itk_image(image, channel_dim=0, dtype=image.dtype)
itk.imwrite(itk_image, "metatensor_to_itk_image.nrrd", True)

Expected behavior
The original and the saved image should be identical.

Screenshots

Original:

image

metatensor_to_itk_image()-ed:

image

Environment

================================
Printing MONAI config...

MONAI version: 1.3.dev2337
Numpy version: 1.25.2
Pytorch version: 2.0.1
MONAI flags: HAS_EXT = False, USE_COMPILED = False, USE_META_DICT = False
MONAI rev id: 57e24b54faa4e7aea1b2d28f9408311fd34543b1
MONAI file: /home//miniconda3/envs/_aim/lib/python3.11/site-packages/monai/init.py

Optional dependencies:
Pytorch Ignite version: NOT INSTALLED or UNKNOWN VERSION.
ITK version: 5.3.0
Nibabel version: 5.1.0
scikit-image version: NOT INSTALLED or UNKNOWN VERSION.
scipy version: NOT INSTALLED or UNKNOWN VERSION.
Pillow version: 9.4.0
Tensorboard version: 2.14.0
gdown version: NOT INSTALLED or UNKNOWN VERSION.
TorchVision version: 0.15.2
tqdm version: 4.66.1
lmdb version: NOT INSTALLED or UNKNOWN VERSION.
psutil version: 5.9.0
pandas version: 2.1.0
einops version: NOT INSTALLED or UNKNOWN VERSION.
transformers version: NOT INSTALLED or UNKNOWN VERSION.
mlflow version: NOT INSTALLED or UNKNOWN VERSION.
pynrrd version: 1.0.0
clearml version: NOT INSTALLED or UNKNOWN VERSION.

For details about installing the optional dependencies, please visit:
https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies

================================
Printing system config...

System: Linux
Linux version: Ubuntu 20.04.6 LTS
Platform: Linux-5.4.0-153-generic-x86_64-with-glibc2.31
Processor: x86_64
Machine: x86_64
Python version: 3.11.5
Process name: python
Command: ['python', '-c', 'import monai; monai.config.print_debug_info()']
Open files: [popenfile(path='/home/ibro/.cursor-server/data/logs/20230913T092831/ptyhost.log', fd=19, position=0, mode='a', flags=33793), popenfile(path='/home/ibro/.cursor-server/data/logs/20230913T092831/remoteagent.log', fd=20, position=4072, mode='a', flags=33793)]
Num physical CPUs: 24
Num logical CPUs: 48
Num usable CPUs: 48
CPU usage (%): [37.5, 1.1, 0.0, 1.1, 1.1, 0.0, 23.6, 6.8, 3.4, 27.0, 11.2, 28.4, 29.2, 0.0, 9.1, 0.0, 13.6, 0.0, 100.0, 0.0, 1.1, 4.5, 100.0, 0.0, 0.0, 0.0, 0.0, 1.1, 0.0, 35.2, 4.5, 21.8, 24.4, 0.0, 1.1, 2.3, 3.4, 1.1, 0.0, 0.0, 0.0, 3.4, 0.0, 5.7, 9.2, 3.4, 0.0, 3.4]
CPU freq. (MHz): 3
Load avg. in last 1, 5, 15 mins (%): [11.8, 11.8, 11.8]
Disk usage (%): 65.3
Avg. sensor temp. (Celsius): UNKNOWN for given OS
Total physical memory (GB): 251.8
Available memory (GB): 217.9
Used memory (GB): 30.2

================================
Printing GPU config...

Num GPUs: 4
Has CUDA: True
CUDA version: 11.8
cuDNN enabled: True
NVIDIA_TF32_OVERRIDE: None
TORCH_ALLOW_TF32_CUBLAS_OVERRIDE: None
cuDNN version: 8700
Current device: 0
Library compiled for CUDA architectures: ['sm_37', 'sm_50', 'sm_60', 'sm_61', 'sm_70', 'sm_75', 'sm_80', 'sm_86', 'sm_90', 'compute_37']
GPU 0 Name: Quadro RTX 8000
GPU 0 Is integrated: False
GPU 0 Is multi GPU board: False
GPU 0 Multi processor count: 72
GPU 0 Total memory (GB): 47.5
GPU 0 CUDA capability (maj.min): 7.5
GPU 1 Name: Quadro RTX 8000
GPU 1 Is integrated: False
GPU 1 Is multi GPU board: False
GPU 1 Multi processor count: 72
GPU 1 Total memory (GB): 47.5
GPU 1 CUDA capability (maj.min): 7.5
GPU 2 Name: Quadro RTX 8000
GPU 2 Is integrated: False
GPU 2 Is multi GPU board: False
GPU 2 Multi processor count: 72
GPU 2 Total memory (GB): 47.5
GPU 2 CUDA capability (maj.min): 7.5
GPU 3 Name: Quadro RTX 8000
GPU 3 Is integrated: False
GPU 3 Is multi GPU board: False
GPU 3 Multi processor count: 72
GPU 3 Total memory (GB): 47.5
GPU 3 CUDA capability (maj.min): 7.5

Additional context
Otherwise, this is a really cool feature, easy ITK <-> MONAI conversion was something that I really missed before, thanks everyone!

@wyli
Copy link
Contributor

wyli commented Sep 14, 2023

thanks, that's a good point, I'll try to enhance the code logic as the current metatensor_to_itk_image assumes itk convention. for now please use LoadImaged(keys=["image"], affine_lps_to_ras=False, reader="ITKReader").

@wyli wyli added the enhancement New feature or request label Sep 14, 2023
@wyli wyli self-assigned this Sep 14, 2023
@ibro45
Copy link
Contributor Author

ibro45 commented Sep 14, 2023

Thanks! Is there a way to achieve that not by changing the LoadImaged args, but by applying something onto the MetaTensor directly?

@wyli
Copy link
Contributor

wyli commented Sep 14, 2023

yes, you can also modify the affine right before metatensor_to_itk_image

image.affine = monai.data.utils.orientation_ras_lps(image.affine)
metatensor_to_itk_image(image...

@ibro45
Copy link
Contributor Author

ibro45 commented Sep 14, 2023

That is great!! Thank you so much 🎉

wyli added a commit that referenced this issue Sep 18, 2023
Fixes #6985

### Description

- update `metatensor_to_itk_image` to  accept RAS metatensor 
- nrrdreader default 'space' from empty/"left-posterior-superior" to
`SpaceKeys.LPS`
- more tests

### Types of changes
<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [x] New tests added to cover the changes.
- [ ] Integration tests passed locally by running `./runtests.sh -f -u
--net --coverage`.
- [x] Quick tests passed locally by running `./runtests.sh --quick
--unittests --disttests`.
- [x] In-line docstrings updated.
- [ ] Documentation updated, tested `make html` command in the `docs/`
folder.

---------

Signed-off-by: Wenqi Li <wenqil@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants