{"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":"![](https://i.imgur.com/5xUFyIP.png)","metadata":{}},{"cell_type":"markdown","source":"# Create Voxel Dataset with KaggleRecipes\nHey fellow Kagglers, I have been working on a GitHub library called **[KaggleRecipes](https://github.com/ayulockin/kagglerecipes)** along with [Morgan](https://www.kaggle.com/morganmcg), my colleague from Weights and Biases, these past few days. The idea for this repository is to package necessary utilities and provide baseline training and inference for the competitions, we are participating in. The repository is also instrumented with Weights and Biases and comes with convenient utilities to visualise your datasets and do efficient, effective model evaluation with W&B.\n\nThis is an **early release** and we are working to add new functionalities and features to abstract away a lot of boiler plate code for your Kaggle competitions. You can find the full documentation **[here](https://ayulockin.github.io/kagglerecipes/)**. \n\n# Created Dataset:\n\nThe following are the dataset created using KaggleRecipes using a single BraTS21ID as reference sequence. \n\n* [RSNA MICCAI Voxel BraTS21ID 143](https://www.kaggle.com/ayuraj/rsna-miccai-voxel-brats21id-143) - Uses BraTS21ID 143 as the reference sequence. \n\n\n## Multiprocessing with `mpire`\nMPIRE is a multiprocessing library recently released that abstracts away a lot of the multi-processing **and** and claims to be faster than `multiprocessing.Pool` and `concurrent.futures.ProcessPoolExecutor` and is on par with ray. This [blog post](https://towardsdatascience.com/mpire-for-python-multiprocessing-is-really-easy-d2ae7999a3e9) introduces it and you can find the [mpire github repo here](https://github.com/Slimmer-AI/mpire/issues/11). \n\nWe've used it in `kagglerecipes` as its really enjoy able to work with (Morgan's favorite features is the simple flag to turn on a tqdm progress bar). We used it to cut down the dicom metadata extraction step in this notebook **from 44minutes to 12minutes**. \n\n## Credits\nThis kernel is possible because of awesome works done by these fellow Kagglers:\n* [Connecting voxel spaces](https://www.kaggle.com/boojum/connecting-voxel-spaces) by [Michael Beregov](https://www.kaggle.com/boojum)\n* [Normalized Voxels: Align Planes and Crop](https://www.kaggle.com/ren4yu/normalized-voxels-align-planes-and-crop) by [yu4u](https://www.kaggle.com/ren4yu)\n* [🧠 DICOM to 2D Resized Axial PNGs 256x256 [x36] 🧠](https://www.kaggle.com/smoschou55/dicom-to-2d-resized-axial-pngs-256x256-x36) by [Sofia Moschou](https://www.kaggle.com/smoschou55)\n\n## Previous Work\n🧐 For a deeper EDA looking at individual mri slices see the [kernel here](https://www.kaggle.com/ayuraj/brain-tumor-eda-and-interactive-viz-with-w-b). <br>\n🧐 You can use this voxel manipulated dataset with this [[Train] Brain Tumor as Video Classification + W&B](https://www.kaggle.com/ayuraj/train-brain-tumor-as-video-classification-w-b) kernel. \n","metadata":{}},{"cell_type":"markdown","source":"# Imports and Setup","metadata":{}},{"cell_type":"code","source":"!pip install -q kagglerecipes","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-09-08T19:53:35.194983Z","iopub.execute_input":"2021-09-08T19:53:35.195468Z","iopub.status.idle":"2021-09-08T19:53:49.831554Z","shell.execute_reply.started":"2021-09-08T19:53:35.195355Z","shell.execute_reply":"2021-09-08T19:53:49.830143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport ast\nimport mpire\nimport wandb\nimport timeit\nimport imageio\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nfrom pathlib import Path\nimport matplotlib.pyplot as plt\n\n# kagglerecipes based imports\nfrom kagglerecipes.preprocess import VoxelData\nfrom kagglerecipes.utils import (\n    get_patient_id,\n    get_all_BraTS21_dicom_meta,\n    get_patient_BraTS21ID_path,\n    get_image_plane,\n    KAGGLE_BRAINTUMOR_META_COLS\n)\nfrom kagglerecipes.wandb_utils import log_to_artifacts","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:54:38.671111Z","iopub.execute_input":"2021-09-08T19:54:38.671479Z","iopub.status.idle":"2021-09-08T19:54:40.306605Z","shell.execute_reply.started":"2021-09-08T19:54:38.671434Z","shell.execute_reply":"2021-09-08T19:54:40.3055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    from kaggle_secrets import UserSecretsClient\n    user_secrets = UserSecretsClient()\n    secret_value_0 = user_secrets.get_secret(\"wandb_api\")\n    wandb.login(key=secret_value_0)\n    anony=None\nexcept:\n    anony = \"must\"\n    print('If you want to use your W&B account, go to Add-ons -> Secrets and provide your W&B access token. Use the Label name as wandb_api. \\nGet your W&B access token from here: https://wandb.ai/authorize')","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:54:40.308072Z","iopub.execute_input":"2021-09-08T19:54:40.308353Z","iopub.status.idle":"2021-09-08T19:54:41.397223Z","shell.execute_reply.started":"2021-09-08T19:54:40.308327Z","shell.execute_reply":"2021-09-08T19:54:41.396051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This is an optional config used to show that you can pass dictionary to log your hyperparameters and othe required info. \nCONFIG = {'competition': 'rsna-miccai-brain', '_wandb_kernel': 'kr_voxel', 'use_wandb': True}","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-09-08T19:54:42.601102Z","iopub.execute_input":"2021-09-08T19:54:42.601719Z","iopub.status.idle":"2021-09-08T19:54:42.606203Z","shell.execute_reply.started":"2021-09-08T19:54:42.601683Z","shell.execute_reply":"2021-09-08T19:54:42.605263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare dataset","metadata":{}},{"cell_type":"code","source":"DATA_PATH = Path('../input/rsna-miccai-brain-tumor-radiogenomic-classification/')\nTRAIN_PATH = DATA_PATH / 'train/'\nSCAN_TYPES = ['FLAIR', 'T1w', 'T1wCE', 'T2w']","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:54:47.57601Z","iopub.execute_input":"2021-09-08T19:54:47.576627Z","iopub.status.idle":"2021-09-08T19:54:47.582248Z","shell.execute_reply.started":"2021-09-08T19:54:47.57657Z","shell.execute_reply":"2021-09-08T19:54:47.581475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load the `train_labels.csv` dataset. \n\nLoad the dataset as W&B artifacts. This will enable data version control since there can be multiple possible dataset that you can create for this competition. Data version control goes a long way to ensure reproducible results, not mess up with a lot going on, share with team and most importantly have a bird eye view of everything. Maybe this [discussion post would be worth a read](https://www.kaggle.com/c/hpa-single-cell-image-classification/discussion/229586). \n\n📌 You can easily log any file or directory using our `log_to_artifacts` function. Check out the [documentation](https://ayulockin.github.io/kagglerecipes/wandb_utils.html#log_to_artifacts).","metadata":{}},{"cell_type":"code","source":"# Load as dataframe.\ntrain_df = pd.read_csv(DATA_PATH / 'train_labels.csv')\n# Exluding three cases\n# Refer: https://www.kaggle.com/c/rsna-miccai-brain-tumor-radiogenomic-classification/discussion/262046\ntrain_df = train_df[train_df.BraTS21ID != 109]\ntrain_df = train_df[train_df.BraTS21ID != 123]\ntrain_df = train_df[train_df.BraTS21ID != 709]\n\nprint(f'Number of BraTS21ID: {len(train_df)}')\n\n# Save the file as W&B artifacts. \nrun = wandb.init(project='rsna-miccai-brain-tumor', \n                 config=CONFIG,  # CONFIG is optional here\n                 job_type='log-dataset-labels',\n                 anonymous=anony) \n\nlog_to_artifacts(path_to_data=DATA_PATH/'train_labels.csv', # 📌\n                artifact_name='raw_rsna_miccai_labels', \n                artifact_type='labels',\n                log='file')\nwandb.finish()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-09-08T21:09:57.733878Z","iopub.execute_input":"2021-09-08T21:09:57.734316Z","iopub.status.idle":"2021-09-08T21:09:57.802631Z","shell.execute_reply.started":"2021-09-08T21:09:57.734277Z","shell.execute_reply":"2021-09-08T21:09:57.801631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Add the path to the patient folders to `train_labels.csv`\n\n📌 Use `get_patient_BraTS21ID_path` to easily get the correct path. Check out the [documentation](https://ayulockin.github.io/kagglerecipes/utils.html#get_patient_BraTS21ID_path).","metadata":{}},{"cell_type":"code","source":"# add path to the df\ntrain_df['path'] = train_df.apply(lambda row: get_patient_BraTS21ID_path(row, TRAIN_PATH), axis=1) # 📌\n\ntrain_df.head(2)","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:56:27.538184Z","iopub.execute_input":"2021-09-08T19:56:27.538801Z","iopub.status.idle":"2021-09-08T19:56:27.571451Z","shell.execute_reply.started":"2021-09-08T19:56:27.538762Z","shell.execute_reply":"2021-09-08T19:56:27.57042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"⭐ For demonstration purposes we are using only 100 patientIds sampled randomly. Comment the cell below to run on the entire dataset. Running on the entire dataset will take around ~90 minutes while using Kaggle kernel. ","metadata":{}},{"cell_type":"code","source":"# train_df = train_df.sample(100).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:56:30.232719Z","iopub.execute_input":"2021-09-08T19:56:30.233483Z","iopub.status.idle":"2021-09-08T19:56:30.237961Z","shell.execute_reply.started":"2021-09-08T19:56:30.233413Z","shell.execute_reply":"2021-09-08T19:56:30.237139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Preprocessing\n\n### Numer of Cores to use - Try Check Your System Specs\nWe can use multiprocessing to handle some of our data processing. To get the best out of your multiprocessing, lets check how many cores are available to use","metadata":{}},{"cell_type":"code","source":"mpire.cpu_count()","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:56:33.397582Z","iopub.execute_input":"2021-09-08T19:56:33.398096Z","iopub.status.idle":"2021-09-08T19:56:33.404702Z","shell.execute_reply.started":"2021-09-08T19:56:33.398065Z","shell.execute_reply":"2021-09-08T19:56:33.403714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In case you're more curious what specs the machine you're using has, [Tim Yee](https://www.kaggle.com/teeyee314) has a nice kernel [here](https://www.kaggle.com/teeyee314/cpu-kernel-specs) that gives you system info.","metadata":{}},{"cell_type":"code","source":"#GPU count and name\n!nvidia-smi -L\n\n#cpu model name\n!lscpu |grep 'Model name'\n\n#no.of sockets i.e available slots for physical processors\n!lscpu | grep 'Socket(s):'\n\n#no.of cores each processor is having\n!lscpu | grep 'Core(s) per socket'\n\n#no.of threads each core is having\n!lscpu | grep 'Thread(s) per core'","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:56:34.746893Z","iopub.execute_input":"2021-09-08T19:56:34.747383Z","iopub.status.idle":"2021-09-08T19:56:38.380957Z","shell.execute_reply.started":"2021-09-08T19:56:34.747352Z","shell.execute_reply":"2021-09-08T19:56:38.379746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The code cell below performs the following steps:\n\n📌 It uses multiprocessing to quickly extract the associated metadata using our `get_all_BraTS21_dicom_meta` function. Check out the [documentation](https://ayulockin.github.io/kagglerecipes/utils.html#get_all_BraTS21_dicom_meta). <br>\n📌 It then extracts the orientation of each DICOM slice using `get_image_place` function. Check out the [documentation](https://ayulockin.github.io/kagglerecipes/utils.html#get_image_plane).\n\n","metadata":{}},{"cell_type":"code","source":"# Number of parallel processes to use for data processing\nn_jobs = 10\n\n# # Get DICOM metadata\ntrain_meta_df = get_all_BraTS21_dicom_meta(train_df, KAGGLE_BRAINTUMOR_META_COLS, \n                                           SCAN_TYPES, n_jobs, True) # 📌\n\n# Get orienation metadata\ntrain_meta_df['Orientation'] = train_meta_df.apply(get_image_plane, axis=1) # 📌\n\n# Save metadata\ntrain_meta_df.to_csv('train_meta_df.csv', index=False)\n\nprint(f'train_meta_df has {len(train_meta_df)} rows')\ntrain_meta_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-08T19:56:54.288788Z","iopub.execute_input":"2021-09-08T19:56:54.289269Z","iopub.status.idle":"2021-09-08T20:08:19.282353Z","shell.execute_reply.started":"2021-09-08T19:56:54.289227Z","shell.execute_reply":"2021-09-08T20:08:19.281235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Save Metadata as W&B Artifacts\n\nAdditionally you can save the metadata as W&B Artifacts. Check out the [official documentation page](https://docs.wandb.ai/guides/artifacts) to learn more. ","metadata":{}},{"cell_type":"code","source":"# Save the file as W&B artifacts. \nrun = wandb.init(project='rsna-miccai-brain-tumor',\n                 config=CONFIG,\n                 job_type='create-dicom-metadata',\n                 anonymous=anony)\n\nlog_to_artifacts(path_to_data='train_meta_df.csv', # we saved the file in the last cell. # 📌\n                artifact_name='metadata',  # let's name it metadata. \n                artifact_type='meta-dataset', # let the type be meta-dataset\n                log='file') \n\nwandb.finish()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-09-08T20:10:02.494916Z","iopub.execute_input":"2021-09-08T20:10:02.495285Z","iopub.status.idle":"2021-09-08T20:10:23.08737Z","shell.execute_reply.started":"2021-09-08T20:10:02.495255Z","shell.execute_reply":"2021-09-08T20:10:23.085928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### [Check out the saved Artifacts page $\\rightarrow$](https://wandb.ai/ayush-thakur/brain-tumor-voxel-dataset/artifacts/meta-dataset/metadata/3debb76d8026375a39aa/files)","metadata":{}},{"cell_type":"markdown","source":"# Create Dataset","metadata":{}},{"cell_type":"markdown","source":"In the cell below you can query the metadata table to find a reference image as the set criteria. \n\ncriteria:\n* Height (`Rows`) and Width (`Columns`)\n* Orientation (`Orientation`)\n* MRI Scan type (`SeriesDescription`)\n* Number of slices (`count`) per `PatientID`\n","metadata":{}},{"cell_type":"code","source":"# Find the reference MRI sequence manually\ndftr2 = train_meta_df[(train_meta_df.Rows == '256') & \n                      (train_meta_df.Columns == '256') &\n                      (train_meta_df.Orientation == \"axial\") &\n                      (train_meta_df.SeriesDescription == \"T1w\")].groupby(['PatientID', 'Orientation', 'SeriesDescription']).size().reset_index(name='count') \n\ndftr2.loc[(dftr2['count'] < 50) & (dftr2['count'] >15)].reset_index(drop = True)","metadata":{"execution":{"iopub.status.busy":"2021-09-08T20:10:39.971524Z","iopub.execute_input":"2021-09-08T20:10:39.971976Z","iopub.status.idle":"2021-09-08T20:10:41.999674Z","shell.execute_reply.started":"2021-09-08T20:10:39.971928Z","shell.execute_reply":"2021-09-08T20:10:41.998834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"⭐Note: If you are using the entire dataset and you have decided on an ID that you want to use as reference, use Run and Save all. ","metadata":{}},{"cell_type":"code","source":"REFERENCE_ID = '00147'","metadata":{"execution":{"iopub.status.busy":"2021-09-08T20:11:19.162078Z","iopub.execute_input":"2021-09-08T20:11:19.162624Z","iopub.status.idle":"2021-09-08T20:11:19.16968Z","shell.execute_reply.started":"2021-09-08T20:11:19.162571Z","shell.execute_reply":"2021-09-08T20:11:19.1683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The cell below have functions responsible to save the voxel manipulated dataset. \n\n📌 The `VoxelData` class contains the main logic for the dataset creation by manipulating the MRI sequences in the Voxel space. It takes `reference_path` which is the reference modality. We will be selecting PatientID `00102` with 23 slices. Check out the [documentation](https://ayulockin.github.io/kagglerecipes/preprocess.html#VoxelData).\n\n📌 The `VoxelData` has a method called`get_voxel_data` which takes in the path to the MRI sequence and returns the manipulated data. ","metadata":{}},{"cell_type":"code","source":" def save_voxel_data(\n     scan_types:list,\n     save_path, \n     reference_path,\n     patient_path,  # Path to the patient folder\n     BraTS21ID:int  # BraTS21ID\n ):\n    \"Returns a re-sampled image based on the reference path\"\n    \n    connect_voxel = VoxelData(reference_path) # 📌\n    \n    # Create folder to save to\n    save_dir = save_path / get_patient_id(BraTS21ID)\n    os.makedirs(save_dir, exist_ok=True)\n\n    # Resample the dicom files and save the output images as numpy files\n    for scan in scan_types:\n        scan_path = os.path.join(patient_path, scan)\n        voxel_data = connect_voxel.get_voxel_data(scan_path) # 📌\n        np.save(save_dir / f'{scan}.npy', voxel_data)\n\n        \ndef save_all_voxel_data(\n    reference_path:str,  # Path to the dicom file to use as a template for resampling\n    save_path:str,  # Path to save voxel data to\n    df,  # Dataframe with path to patient folder and BraTS21ID\n    scan_types:list=['FLAIR', 'T1w', 'T1wCE', 'T2w'],  # The subfolders in the patient data to loop through\n):    \n    \"Resamples the dicom data based on reference template dicom and then saves that voxel data to save_path\"\n    \n    patient_path = df.path.values\n    BraTS21ID_ls = df.BraTS21ID.values\n    results = []\n    for i in tqdm(range(len(df))):\n        res = save_voxel_data(scan_types, save_path, reference_path, patient_path[i], BraTS21ID_ls[i])\n        results.append(res)","metadata":{"execution":{"iopub.status.busy":"2021-09-08T20:11:24.210341Z","iopub.execute_input":"2021-09-08T20:11:24.210768Z","iopub.status.idle":"2021-09-08T20:11:24.221702Z","shell.execute_reply.started":"2021-09-08T20:11:24.210734Z","shell.execute_reply":"2021-09-08T20:11:24.220287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"REFERENCE_PATH = os.path.join(TRAIN_PATH / REFERENCE_ID, \"T1w\") # Note: The PatientID and the MRI Scan type selected as reference.\nSAVE_PATH = Path('../tmp/') \n\nos.makedirs(SAVE_PATH, exist_ok=True)\n\n# Save all data\nsave_all_voxel_data(REFERENCE_PATH, SAVE_PATH, train_df)","metadata":{"execution":{"iopub.status.busy":"2021-09-08T20:11:29.254683Z","iopub.execute_input":"2021-09-08T20:11:29.255288Z","iopub.status.idle":"2021-09-08T21:04:19.018363Z","shell.execute_reply.started":"2021-09-08T20:11:29.255251Z","shell.execute_reply":"2021-09-08T21:04:19.012652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize the Created Dataset as W&B Tables\n\nThis allows you to interactively check if the created dataset is correct. \n\n🧐 For a deeper EDA looking at individual images see this **[kernel here](https://www.kaggle.com/ayuraj/brain-tumor-eda-and-interactive-viz-with-w-b)**\n\n⚠️ See this discussion post for more info on MGMT and the objective of this competition: **[[Self-Note] \"Brain tumor classification\" is misleading!](https://www.kaggle.com/c/rsna-miccai-brain-tumor-radiogenomic-classification/discussion/264861)**","metadata":{}},{"cell_type":"code","source":"# Number of scans to viz\nNUM_SAMPLES = 32\n\n# Initialize a W&B run to log images\nrun = wandb.init(project='rsna-miccai-brain-tumor',\n                 config=CONFIG,\n                 name='viz-dataset-tables',\n                 anonymous=anony) # 📌 W&B Code 1\n\ndata_at = wandb.Table(columns=['patient_id', 'target', 'FLAIR', 'T1w', 'T1wCE', 'T2w']) # 📌 W&B Code 2\n\nfor i in tqdm(range(len(train_df))):\n    os.makedirs('tables-gif', exist_ok=True)\n    \n    row = train_df.loc[i]\n    patient_id = get_patient_id(row.BraTS21ID)\n    \n    for j, key in enumerate(SCAN_TYPES):\n        _frames = np.load(f'{SAVE_PATH}/{patient_id}/{key}.npy')\n        imageio.mimsave(f'tables-gif/out_{patient_id}_{j}.gif', (_frames*255).astype('uint8'))\n    \n    data_at.add_data(patient_id,                                            \n                     row.MGMT_value,\n                     wandb.Image(f'tables-gif/out_{patient_id}_0.gif'),\n                     wandb.Image(f'tables-gif/out_{patient_id}_1.gif'),\n                     wandb.Image(f'tables-gif/out_{patient_id}_2.gif'),\n                     wandb.Image(f'tables-gif/out_{patient_id}_3.gif')) # 📌 W&B Code 3\n    \n    if i == NUM_SAMPLES:\n        break\n\nwandb.log({'MRI Sequencing Dataset': data_at}) # 📌 W&B Code 4\nwandb.finish() # 📌 W&B Code 5","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-09-02T15:44:31.911768Z","iopub.execute_input":"2021-09-02T15:44:31.912268Z","iopub.status.idle":"2021-09-02T15:46:08.405793Z","shell.execute_reply.started":"2021-09-02T15:44:31.912226Z","shell.execute_reply":"2021-09-02T15:46:08.405002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Visualize entire dataset interactively\n\n### [Check out the Tables](https://wandb.ai/ayush-thakur/brain-tumor-viz/runs/kb9nwx3a) \n\n![img](https://i.imgur.com/4cGorA3.gif)","metadata":{}},{"cell_type":"markdown","source":"You would want to save the created dataset as Kaggle Dataset which is not covered in this Kernel. But if you are pushing out the dataset as public Kaggle dataset if would be great if you can use the title something like: `RSNA-MICCAI Voxel Dataset BraTS21Id <PatientID>`\n\n**If you like the effort consider upvoting and using the library :)**","metadata":{}},{"cell_type":"code","source":"!zip -rq voxel.zip ../tmp","metadata":{"execution":{"iopub.status.busy":"2021-09-08T21:09:02.491571Z","iopub.execute_input":"2021-09-08T21:09:02.492085Z","iopub.status.idle":"2021-09-08T21:09:19.582436Z","shell.execute_reply.started":"2021-09-08T21:09:02.492045Z","shell.execute_reply":"2021-09-08T21:09:19.581557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Done!')","metadata":{"execution":{"iopub.status.busy":"2021-09-02T15:52:21.0714Z","iopub.execute_input":"2021-09-02T15:52:21.071925Z","iopub.status.idle":"2021-09-02T15:52:21.077654Z","shell.execute_reply.started":"2021-09-02T15:52:21.071883Z","shell.execute_reply":"2021-09-02T15:52:21.076506Z"},"trusted":true},"execution_count":null,"outputs":[]}]}