{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"In this notebook, we will use [TorchIO](http://torchio.rtfd.io/) and its new [`RSNAMICCAI`](https://torchio.readthedocs.io/datasets.html#rsnamiccai) dataset class to load, preprocess and write the challenge dataset.","metadata":{}},{"cell_type":"code","source":"!pip install -q torchio==0.18.53","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:37:31.580320Z","iopub.execute_input":"2021-09-05T10:37:31.580748Z","iopub.status.idle":"2021-09-05T10:37:49.548576Z","shell.execute_reply.started":"2021-09-05T10:37:31.580658Z","shell.execute_reply":"2021-09-05T10:37:49.547385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\nimport torch\nimport torchio as tio\nimport matplotlib.pyplot as plt\n\nplt.rcParams[\"figure.figsize\"] = (12, 10)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:37:49.550942Z","iopub.execute_input":"2021-09-05T10:37:49.551359Z","iopub.status.idle":"2021-09-05T10:37:51.767554Z","shell.execute_reply.started":"2021-09-05T10:37:49.551317Z","shell.execute_reply":"2021-09-05T10:37:51.766351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"root_dir = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification'\ndataset = tio.datasets.RSNAMICCAI(root_dir)\nlen(dataset)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:37:51.769262Z","iopub.execute_input":"2021-09-05T10:37:51.769618Z","iopub.status.idle":"2021-09-05T10:38:41.235241Z","shell.execute_reply.started":"2021-09-05T10:37:51.769587Z","shell.execute_reply":"2021-09-05T10:38:41.234341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subject = dataset[0]\nsubject","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:38:41.236621Z","iopub.execute_input":"2021-09-05T10:38:41.236905Z","iopub.status.idle":"2021-09-05T10:38:54.981277Z","shell.execute_reply.started":"2021-09-05T10:38:41.236880Z","shell.execute_reply":"2021-09-05T10:38:54.980341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(subject.BraTS21ID)\nprint(subject.MGMT_value)\nprint(subject.T1w)\nprint(subject.T1wCE)\nprint(subject.T2w)\nprint(subject.FLAIR)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:38:54.982514Z","iopub.execute_input":"2021-09-05T10:38:54.982820Z","iopub.status.idle":"2021-09-05T10:38:55.008285Z","shell.execute_reply.started":"2021-09-05T10:38:54.982789Z","shell.execute_reply":"2021-09-05T10:38:55.007133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subject.plot(reorient=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:38:55.009965Z","iopub.execute_input":"2021-09-05T10:38:55.010292Z","iopub.status.idle":"2021-09-05T10:38:58.603131Z","shell.execute_reply.started":"2021-09-05T10:38:55.010242Z","shell.execute_reply":"2021-09-05T10:38:58.602405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Results with these raw data will not be good because the images have different orientations, shapes and voxel sizes, i.e., they are in different voxel spaces. We need to preprocess the dataset to put images in the same voxel space. TorchIO to the rescue.","metadata":{}},{"cell_type":"code","source":"preprocessing_transforms = (\n    tio.ToCanonical(),\n    tio.Resample(1, image_interpolation='bspline'),\n    tio.Resample('T1w', image_interpolation='nearest'),\n)\npreprocess = tio.Compose(preprocessing_transforms)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:38:58.604317Z","iopub.execute_input":"2021-09-05T10:38:58.604757Z","iopub.status.idle":"2021-09-05T10:38:58.609318Z","shell.execute_reply.started":"2021-09-05T10:38:58.604710Z","shell.execute_reply":"2021-09-05T10:38:58.608408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We use [`ToCanonical`](https://torchio.readthedocs.io/transforms/preprocessing.html#tocanonical) to have a consistent orientation, [`Resample`](https://torchio.readthedocs.io/transforms/preprocessing.html#resample) the images to 1 mm isotropic spacing, and [`Resample`](https://torchio.readthedocs.io/transforms/preprocessing.html#resample) again to match the field of view of one of the images (the second resampling is lossless as images are already in the same voxel space).","metadata":{}},{"cell_type":"markdown","source":"Let's create datasets that apply our preprocessing transform after loading the images.","metadata":{}},{"cell_type":"code","source":"train_set = tio.datasets.RSNAMICCAI(root_dir, train=True, transform=preprocess)\ntest_set = tio.datasets.RSNAMICCAI(root_dir, train=False, transform=preprocess)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:38:58.611350Z","iopub.execute_input":"2021-09-05T10:38:58.611734Z","iopub.status.idle":"2021-09-05T10:39:10.454280Z","shell.execute_reply.started":"2021-09-05T10:38:58.611705Z","shell.execute_reply":"2021-09-05T10:39:10.453364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To avoid resampling during training, which is computationally expensive, we preprocess our images now and save a new dataset to disk.\n\nUse `demo=False` to preprocess all images in the dataset.","metadata":{}},{"cell_type":"code","source":"def preprocess_dataset(dataset, out_dir, parallel=True, demo=True):\n    import shutil\n    import multiprocessing as mp\n    from pathlib import Path\n    from tqdm.notebook import tqdm\n    if demo:  # just to showcase TorchIO\n        dataset._subjects = dataset._subjects[:5]\n    out_dir = Path(out_dir)\n    labels_name = 'train_labels.csv'\n    out_dir.mkdir(exist_ok=True, parents=True)\n    shutil.copy(dataset.root_dir / labels_name, out_dir / labels_name)\n    subjects_dir = out_dir / ('train' if dataset.train else 'test')\n    if parallel:\n        loader = torch.utils.data.DataLoader(\n            dataset,\n            num_workers=mp.cpu_count(),\n            collate_fn=lambda x: x[0],\n        )\n        iterable = loader\n    else:\n        iterable = dataset\n    for subject in tqdm(iterable):\n        subject_dir = subjects_dir / subject.BraTS21ID\n        for name, image in tqdm(subject.get_images_dict().items(), leave=False):\n            image_dir = subject_dir / name\n            image_dir.mkdir(exist_ok=True, parents=True)\n            image_path = image_dir / f'{name}.nii.gz'\n            image.save(image_path)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:39:10.455551Z","iopub.execute_input":"2021-09-05T10:39:10.455825Z","iopub.status.idle":"2021-09-05T10:39:10.465300Z","shell.execute_reply.started":"2021-09-05T10:39:10.455799Z","shell.execute_reply":"2021-09-05T10:39:10.464558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out_dir = 'rsna-preprocessed'\nif not Path(out_dir).is_dir():\n    preprocess_dataset(train_set, out_dir)\n    preprocess_dataset(test_set, out_dir)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:39:10.466287Z","iopub.execute_input":"2021-09-05T10:39:10.466673Z","iopub.status.idle":"2021-09-05T10:43:29.048885Z","shell.execute_reply.started":"2021-09-05T10:39:10.466645Z","shell.execute_reply":"2021-09-05T10:43:29.047579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"new_train_set = tio.datasets.RSNAMICCAI(out_dir, train=True)\nnew_test_set = tio.datasets.RSNAMICCAI(out_dir, train=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:43:29.050499Z","iopub.execute_input":"2021-09-05T10:43:29.050821Z","iopub.status.idle":"2021-09-05T10:43:29.063159Z","shell.execute_reply.started":"2021-09-05T10:43:29.050784Z","shell.execute_reply":"2021-09-05T10:43:29.062101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"subject = new_train_set[0]\nsubject.plot(reorient=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-05T10:43:29.064624Z","iopub.execute_input":"2021-09-05T10:43:29.064963Z","iopub.status.idle":"2021-09-05T10:43:32.022331Z","shell.execute_reply.started":"2021-09-05T10:43:29.064934Z","shell.execute_reply":"2021-09-05T10:43:32.021139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"That's better! All images are now in the same voxel space.","metadata":{}},{"cell_type":"markdown","source":"Training can now be performed as usual, [combining TorchIO with other libraries like PyTorch Lightning and MONAI](https://colab.research.google.com/github/fepegar/torchio-notebooks/blob/main/notebooks/TorchIO_MONAI_PyTorch_Lightning.ipynb).","metadata":{}}]}