question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mixing MONAI and TorchIO transforms in OneOf with batched data leads to RuntimeError

See original GitHub issue

Describe the bug Mixing MONAI and TorchIO transforms in the same OneOf instance with batched data leads to RuntimeError: each element in list of batch should be of equal size, even though both transforms within OneOf seem to produce tensors of the same size. Using MONAI transforms only or TorchIO transforms only within a given OneOf instance works with batched data. Would like to be able to combine both within a given OneOf instance.

To Reproduce The following example, adapted from the 3D spleen segmentation tutorial, should reproduce the error:

import glob
import os
import tempfile

from monai.apps import download_and_extract
from monai.config import print_config
from monai.data import DataLoader, Dataset
import monai.transforms as tf
from monai.utils import first, set_determinism
import torchio as tio

print_config()

directory = os.environ.get("MONAI_DATA_DIRECTORY")
root_dir = tempfile.mkdtemp() if directory is None else directory
print(root_dir)

resource = "https://msd-for-monai.s3-us-west-2.amazonaws.com/Task09_Spleen.tar"
md5 = "410d4a301da4e5b2f6f86ec3ddba524e"

compressed_file = os.path.join(root_dir, "Task09_Spleen.tar")
data_dir = os.path.join(root_dir, "Task09_Spleen")
if not os.path.exists(data_dir):
    download_and_extract(resource, compressed_file, root_dir, md5)

train_images = sorted(
    glob.glob(os.path.join(data_dir, "imagesTr", "*.nii.gz")))
train_labels = sorted(
    glob.glob(os.path.join(data_dir, "labelsTr", "*.nii.gz")))
data_dicts = [
    {"image": image_name, "label": label_name}
    for image_name, label_name in zip(train_images, train_labels)
]
train_files, val_files = data_dicts[:-9], data_dicts[-9:]

set_determinism(seed=0)

oneof_transforms = [
    tf.RandAdjustContrastd(
        keys=['image'],
        prob=1.0
    ),
    tf.Compose([
        tf.ToTensord(keys=['image', 'label']),
        tio.transforms.RandomBlur(
            p=1.0,
            include=['image']
        ),
        tf.ToNumpyd(keys=['image', 'label'])
    ])
]

train_transforms = tf.Compose([
    tf.LoadImaged(keys=["image", "label"]),
    tf.EnsureChannelFirstd(keys=["image", "label"]),
    tf.Spacingd(keys=["image", "label"], pixdim=(
        1.5, 1.5, 2.0), mode=("bilinear", "nearest")),
    tf.Orientationd(keys=["image", "label"], axcodes="RAS"),
    tf.ScaleIntensityRanged(
        keys=["image"], a_min=-57, a_max=164,
        b_min=0.0, b_max=1.0, clip=True,
    ),
    tf.CropForegroundd(keys=["image", "label"], source_key="image"),
    tf.OneOf(transforms=oneof_transforms),
    tf.RandCropByPosNegLabeld(
        keys=["image", "label"],
        label_key="label",
        spatial_size=(96, 96, 96),
        pos=1,
        neg=1,
        num_samples=4,
        image_key="image",
        image_threshold=0,
    ),
    tf.EnsureTyped(keys=["image", "label"]),
])

ds = Dataset(data=train_files, transform=train_transforms)
loader = DataLoader(ds, batch_size=2, shuffle=True)

for batch_data in loader:
    continue

Expected behavior I would expect the dataloader to be able to collate the samples within a batch if the two samples have the same size (e.g., [4, 1, 96, 96, 96] for the example above) even if they’re transformed by transforms from different libraries (i.e., MONAI and TorchIO). With that said, I’m not too familiar with the low-level details of the dataloader and collate functions, so I could be missing an important detail.

Screenshots image

Environment

================================
Printing MONAI config...
================================
MONAI version: 0.7.dev2133
Numpy version: 1.19.2
Pytorch version: 1.8.1+cu102
MONAI flags: HAS_EXT = False, USE_COMPILED = False
MONAI rev id: 20ffa3f987fad60a8428ec635fb0b4f6ccca9747

Optional dependencies:
Pytorch Ignite version: NOT INSTALLED or UNKNOWN VERSION.
Nibabel version: 3.2.1
scikit-image version: NOT INSTALLED or UNKNOWN VERSION.
Pillow version: 7.2.0
Tensorboard version: NOT INSTALLED or UNKNOWN VERSION.
gdown version: NOT INSTALLED or UNKNOWN VERSION.
TorchVision version: 0.9.1+cu102
tqdm version: 4.60.0
lmdb version: NOT INSTALLED or UNKNOWN VERSION.
psutil version: NOT INSTALLED or UNKNOWN VERSION.
pandas version: 1.2.4
einops 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...
================================
`psutil` required for `print_system_info`

================================
Printing GPU config...
================================
Num GPUs: 0
Has CUDA: False
cuDNN enabled: True
cuDNN version: 7605

Additional context N/A

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (9 by maintainers)

github_iconTop GitHub Comments

3reactions
rijobrocommented, Aug 20, 2021

I’ve done some messing around and think the problem is due to differences in the image_transforms. If RandAdjustConstrastd is used, an extra element will be in the list compared to the torchio transform. Adding tf.DeleteItemsd(keys=["image_transforms", "label_transforms"]), at the end of the transforms worked for me.

But certainly something that we need to think about for avoiding this in the future. Thanks for raising this!

0reactions
lyndonboonecommented, Aug 20, 2021

Thanks @rijobro , that seems to do the trick! Much appreciated.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error if CropOrPad and RescaleIntensity are used together
Bug I have an error when using 'CropOrPad' and 'RescaleIntensity' as part of the dataset transformations. Note that there is no error if...
Read more >
Transforms - TorchIO - Read the Docs
TorchIO transforms take as input instances of Subject or Image (and its subclasses), 4D PyTorch tensors, 4D NumPy arrays, SimpleITK images, NiBabel images, ......
Read more >
TorchIO is a Medical image preprocessing and augmentation ...
TorchIO : a Python library for efficient loading, preprocessing, augmentation and patch-based sampling of medical images in deep learning.
Read more >
MONAI - githubmemory
MONAI repo issues. ... Tensor computation for Brats transforms ... Mixing MONAI and TorchIO transforms in OneOf with batched data leads to RuntimeError....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found