{"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":"# 1. Introduction\n\n<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>1.1 Context</b></p>\n</div>\n\nThis coding challenge is organized by the [Radiological Society of North America (RSNA)](https://www.rsna.org/) together with the [American Society of Neuroradiology (ASNR)]( https://www.asnr.org/) and the [American Society of Spine Radiology (ASSR)](https://www.theassr.org/) to explore whether AI can be used to help detect and localize cervical spine fractures.\n\n“To create the ground truth dataset, the challenge planning task force collected imaging data sourced from twelve sites on six continents, including approximately 3,000 CT studies. Spine radiology specialists from the ASNR and ASSR provided expert image level annotations these studies to indicate the presence, vertebral level and location of any cervical spine fractures.” [(Competition description)]( https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/overview/description)\n\nThe goal is to match the radiologist’s performance in the detection and localization of fractures to the seven vertebrae that comprise the cervical spine (C1-C7 – see 1.2 Task).\n\n**Why?**\n“Over 1.5 million spine fractures occur annually in the United States alone resulting in over 17,730 spinal cord injuries annually. The most common site of spine fracture is the cervical spine. There has been a rise in the incidence of spinal fractures in the elderly and in this population, fractures can be more difficult to detect on imaging due to superimposed degenerative disease and osteoporosis. Imaging diagnosis of adult spine fractures is now almost exclusively performed with computed tomography (CT) instead of radiographs (x-rays). Quickly detecting and determining the location of any vertebral fractures is essential to prevent neurologic deterioration and paralysis after trauma.” [(Competition description)]( https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/overview/description)\n\n\n","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>1.2 Task</b></p>\n</div>\n\nThe task is, based on the input of CT images, to determine whether there are any fractures in one of the seven vertebrae that comprise of the cervical spine (C1-C7). Fractures in the skull base, thoracic spine, ribs, and clavicles are ignored. \n\nThe model must determine whether there are any fractures and in which vertebrae they occur. Per patient there are 8 expected outputs: One for each of the seven cervical vertebrae and one “any” which indicates whether the patient has a fracture of any kind or not. \n\n<center>\n<img src=\"https://cdn.britannica.com/57/54757-050-99173B1B/Human-vertebral-column.jpg\" style=\"max-width:800px\">\n<div style>Anatomy - Vertebral Column <a href=\"https://www.britannica.com/science/vertebral-column\">(britannica.com)</a></div>\n</center>\n\n<hr>\n\n*Competition timeline:*\n    \n* Start date - 28th July 2022\n* Entry Deadline - 20th October 2022\n* Finals Submission Deadline - 27th October 2022\n\n*All deadlines are at 11:59 PM UTC on the corresponding day unless otherwise noted.*","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>1.3 Evaluation metric</b></p>\n</div>\n\n\"Submissions are evaluated using a **weighted multi-label logarithmic loss**. Each fracture sub-type is its own row for every exam, and you are expected to predict a probability for a fracture at each of the seven cervical vertebrae designated as C1, C2, C3, C4, C5, C6 and C7. There is also an any label, patient_overall, which indicates that a fracture of ANY kind described before exists in the examination. Fractures in the skull base, thoracic spine, ribs, and clavicles are ignored. The **any label is weighted more highly than specific fracture level sub-types**.\n\nFor each exam Id, you must submit a set of predicted probabilities (a separate row for each cervical level subtype). We then take the log loss for each predicted probability versus its true label.\"[(Competition Evaluation)](https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/overview/evaluation)\n\nThe binary weighted log loss function for label j on exam i is specified as:\n\n$\n\\Large L_{ij} = - w_j \\left(y_{ij} \\log(p_{ij}) + (1-y_{ij}) \\log(1-p_{ij})  \\right)\n$\n\nThe loss is averaged across al rows. \n\n\n**Weights ([from Competition Host](https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/discussion/340392)):**\n* Vertebrae negative: 1\n* Vertebrae positive: 2\n* Patient negative: 7\n* Patient positive: 14\n\n<hr>\n\nThe final output should have 8 rows per image. There will be 2 columns (row_id and fractured). \n<br>\n\nThe row id is buit as follows:\n<br>\n**[image Id]_[Sub-type Name]**\n<br>\nExample: 1.2.826.0.1.3680043.10197_C1\n\n\nFor each image ID in the test set, the probability for each of the different possible sub-types and the patient overall must be predicted. ","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>1.4 Code requirements</b></p>\n</div>\n\nSubmissions must be made through **Notebooks**. In order for the \"Submit\" button to be active after a commit, the following conditions must be met:\n\n* CPU Notebook <= 9 hours run-time\n* GPU Notebook <= 9 hours run-time\n* Internet access **disabled**\n* Freely & publicly available external data is **allowed**, including pre-trained models\n* Submission file must be named **submission.csv**","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>1.5 Libraries</b></p>\n</div>\n\nTo use the dependencies gdcm and pylibjgpeg that are needed to ensure that all images can be displayed correctly, the [Pydicom Utility](https://www.kaggle.com/datasets/ipythonx/for-pydicom) dataset by [M.Innat](https://www.kaggle.com/ipythonx/datasets) can be used. This ensures that the files can also be used correctly offline. ","metadata":{}},{"cell_type":"code","source":"# From https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda\n'''Offline (need to add dataset --> for-pydicom)'''\n!pip install -qU ../input/for-pydicom/python_gdcm-3.0.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl ../input/for-pydicom/pylibjpeg-1.4.0-py3-none-any.whl --find-links frozen_packages --no-index","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:12.698071Z","iopub.execute_input":"2022-09-01T04:40:12.698502Z","iopub.status.idle":"2022-09-01T04:40:25.948937Z","shell.execute_reply.started":"2022-09-01T04:40:12.698454Z","shell.execute_reply":"2022-09-01T04:40:25.947986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd \nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport seaborn as sns\nimport pydicom\nimport nibabel as nib\nimport os\n\nfrom pprint import pprint\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom tqdm import tqdm\nfrom glob import glob","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:25.951397Z","iopub.execute_input":"2022-09-01T04:40:25.951746Z","iopub.status.idle":"2022-09-01T04:40:26.925096Z","shell.execute_reply.started":"2022-09-01T04:40:25.951714Z","shell.execute_reply":"2022-09-01T04:40:26.924124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Data\n<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>2.1 Data frames</b></p>\n</div>\n\nThe data provided consists of 4 different CSV files ans 3 folders that contain images and segmentations.","metadata":{}},{"cell_type":"code","source":"# Files\n!ls ../input/rsna-2022-cervical-spine-fracture-detection","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:26.926885Z","iopub.execute_input":"2022-09-01T04:40:26.92733Z","iopub.status.idle":"2022-09-01T04:40:28.061944Z","shell.execute_reply.started":"2022-09-01T04:40:26.927287Z","shell.execute_reply":"2022-09-01T04:40:28.060712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>","metadata":{}},{"cell_type":"code","source":"# Set example path\nexample_path = \"../input/rsna-2022-cervical-spine-fracture-detection/train_images/1.2.826.0.1.3680043.10443/1.dcm\"\n\n# Load metadata\ntrain_data = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/train.csv\")\ntrain_bbox = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/train_bounding_boxes.csv\")\ntest_data = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/test.csv\")\nsample_submission = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/sample_submission.csv\")\n\n# Print shapes of data\nprint('training data shape:', train_data.shape)\nprint('training bounding boxes shape:', train_bbox.shape)\nprint('test data shape:', test_data.shape)\nprint('sample submission shape:', sample_submission.shape)","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.066423Z","iopub.execute_input":"2022-09-01T04:40:28.067253Z","iopub.status.idle":"2022-09-01T04:40:28.126389Z","shell.execute_reply.started":"2022-09-01T04:40:28.067202Z","shell.execute_reply":"2022-09-01T04:40:28.125094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n\n## Training Data\n\n* **StudyInstanceUID** -> Study ID which is unique for each patient scan.\n* **patient_overall** -> Patient overview, meaning whether any vertebrae has a fracture.\n* **C1-C7** -> Indicating whether a vertebray is fractured or not.","metadata":{}},{"cell_type":"code","source":"train_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.127496Z","iopub.execute_input":"2022-09-01T04:40:28.128104Z","iopub.status.idle":"2022-09-01T04:40:28.156235Z","shell.execute_reply.started":"2022-09-01T04:40:28.128072Z","shell.execute_reply":"2022-09-01T04:40:28.15501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n\n## Bounding Box Data\n\n* **StudyInstanceUID** -> Study ID which is unique for each patient scan.\n* **x** -> x coordinate of the bottom left corner of the bounding box*\n* **y** -> y coordinate of the bottom left corner of the bounding box*\n* **width** -> width of the bounding box\n* **height** -> height of the bounding box\n* **slice_number** -> slice number of the scan\n\n*The coordinates of the bounding box are for the bottom left corner and not in the center as per usual convention. See the comments here: https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda/comments","metadata":{}},{"cell_type":"code","source":"train_bbox.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.157654Z","iopub.execute_input":"2022-09-01T04:40:28.157996Z","iopub.status.idle":"2022-09-01T04:40:28.173397Z","shell.execute_reply.started":"2022-09-01T04:40:28.157963Z","shell.execute_reply":"2022-09-01T04:40:28.172202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n\n## Test Data\n\n* **row_id** -> The row ID. This will match the same column in the sample submission file.\n* **StudyInstanceUID** -> Study ID which is unique for each patient scan.\n* **prediction_type** -> Which one of the eight target columns needs a prediction in this row.","metadata":{}},{"cell_type":"code","source":"test_data.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.175087Z","iopub.execute_input":"2022-09-01T04:40:28.176366Z","iopub.status.idle":"2022-09-01T04:40:28.18794Z","shell.execute_reply.started":"2022-09-01T04:40:28.176322Z","shell.execute_reply":"2022-09-01T04:40:28.187141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n\n## Sample Submission\n\n* **row_id** -> Unique to each patient scan including the concerned vertebrae.\n* **fractured** -> Target column with prediction.","metadata":{}},{"cell_type":"code","source":"sample_submission.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.189414Z","iopub.execute_input":"2022-09-01T04:40:28.192225Z","iopub.status.idle":"2022-09-01T04:40:28.205064Z","shell.execute_reply.started":"2022-09-01T04:40:28.192181Z","shell.execute_reply":"2022-09-01T04:40:28.204195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Exploratory Data Analysis (EDA)\n<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>3.1 Data Analysis</b></p>\n</div>\n\nThe overall split of the data is 1058 (52.4% no fracture) and 961 (47.6% with fracture). Of the patients with fractures, there are several patients that have more than one fracture.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10, 7))\nax = sns.countplot(data=train_data, x=\"patient_overall\")\nfor container in ax.containers:\n    ax.bar_label(container)\nax.set_title(\"Fractured patient count\", weight=\"bold\", size=19)\nsns.despine(right=True, top=True, left=True);","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.206599Z","iopub.execute_input":"2022-09-01T04:40:28.207359Z","iopub.status.idle":"2022-09-01T04:40:28.443487Z","shell.execute_reply.started":"2022-09-01T04:40:28.207314Z","shell.execute_reply":"2022-09-01T04:40:28.442392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>","metadata":{}},{"cell_type":"markdown","source":"The most fractures appear in the upper and lower vertebrae with **C7 (27.22%)** and **C2 (19.74%)** with the highest portion. **C3 (5.06%)** and **C4 (7.48%)** have the lowest portion.","metadata":{}},{"cell_type":"code","source":"data_count = pd.melt(train_data, \n             id_vars=['StudyInstanceUID', 'patient_overall'],\n             var_name=\"Vertebrae\",\n             value_name=\"Flag\")\n\nplt.figure(figsize=(15, 7))\nax = sns.countplot(data=data_count, x=\"Vertebrae\", hue=\"Flag\")\nfor container in ax.containers:\n    ax.bar_label(container)\nax.set_title(\"Fractured Vertebrae type count\", weight=\"bold\", size=19)\nsns.despine(right=True, top=True, left=True);","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.447017Z","iopub.execute_input":"2022-09-01T04:40:28.447333Z","iopub.status.idle":"2022-09-01T04:40:28.789668Z","shell.execute_reply.started":"2022-09-01T04:40:28.447304Z","shell.execute_reply":"2022-09-01T04:40:28.78849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"percentage_table = data_count[[\"Vertebrae\",\"Flag\"]].groupby(\"Vertebrae\").sum()\npercentage_table[\"percentage\"] = np.round((percentage_table[\"Flag\"] / percentage_table[\"Flag\"].sum())*100,2)\npercentage_table","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.790913Z","iopub.execute_input":"2022-09-01T04:40:28.791246Z","iopub.status.idle":"2022-09-01T04:40:28.814669Z","shell.execute_reply.started":"2022-09-01T04:40:28.791218Z","shell.execute_reply":"2022-09-01T04:40:28.813647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n\nIf a patient has **multiple fractures**, then they are more likely to be on a **bordering vertebra**.\nFor example a fracture in C1 will more likely be next to a fracture in C2 then in C5.","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(10,7))\ncorr = train_data[['C1','C2','C3','C4','C5','C6','C7']].corr()\nsns.heatmap(corr, cmap=\"seismic\", vmin=-1, vmax=1)\nplt.title('Correlations')","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:28.816018Z","iopub.execute_input":"2022-09-01T04:40:28.816325Z","iopub.status.idle":"2022-09-01T04:40:29.114579Z","shell.execute_reply.started":"2022-09-01T04:40:28.816298Z","shell.execute_reply":"2022-09-01T04:40:29.113497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>3.2 Patient ID's</b></p>\n</div>\n\nEach patient has a **unique ID** which is used to identiy the patient. This is also the ID that has to be used for the output (submission) in combination with the vertebrae and the overall evaluation (see 1.3 Evaluation metric).","metadata":{}},{"cell_type":"code","source":"for x in range(20):\n    print(train_data[\"StudyInstanceUID\"][x])","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:29.116016Z","iopub.execute_input":"2022-09-01T04:40:29.116322Z","iopub.status.idle":"2022-09-01T04:40:29.12248Z","shell.execute_reply.started":"2022-09-01T04:40:29.116294Z","shell.execute_reply":"2022-09-01T04:40:29.121409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n<br>\n\nWhen looking at the Study ID's, the assumption arises that only the numbers after the last period are unique. The code below by [Samual Cortinhas](https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda) confirms that assumption.","metadata":{}},{"cell_type":"code","source":"for i in range(7):\n    print(train_data['StudyInstanceUID'].map(lambda x : x.split('.')[i]).unique())","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:29.124067Z","iopub.execute_input":"2022-09-01T04:40:29.124468Z","iopub.status.idle":"2022-09-01T04:40:29.145116Z","shell.execute_reply.started":"2022-09-01T04:40:29.124427Z","shell.execute_reply":"2022-09-01T04:40:29.143996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Images\n<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>4.1 Digital Imaging and Communications in Medicine (DICOM)</b></p>\n</div>\n\n\"DICOM, from an informatics and community standpoint, is one of the most successful efforts for a standard that we can think of. DICOM stands for Digital Imaging and Communications in Medicine, and since its creation in the early 1980’s, has been the bread and butter for the storage and transfer of medical imaging datasets. It’s so much more than a file format, or a transfer protocol, DICOM defines both formats, quality standards, and transfer protocols for clinical use.\"[(pydicom - about)](https://pydicom.github.io/about)\n\nTo open DICOM files the [Pydicom library](https://pydicom.github.io/) can be used.\n\nThe Pixel data of the file contains the image. Other usefull information is stored in the metadate such as the size of the image **(Rows and Columns)**, the thickness of the slice **(Slice Thickness)** as well as the patient **(Patient ID)** and study ID **(Study Instance ID)** and the slice number **(Instance Number)**.","metadata":{}},{"cell_type":"code","source":"# example_path declared in 2.1 Data Frames\ndcm_example = pydicom.dcmread(example_path)\ndcm_example","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:29.146291Z","iopub.execute_input":"2022-09-01T04:40:29.146595Z","iopub.status.idle":"2022-09-01T04:40:29.16972Z","shell.execute_reply.started":"2022-09-01T04:40:29.146568Z","shell.execute_reply":"2022-09-01T04:40:29.168393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>","metadata":{}},{"cell_type":"code","source":"# from https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda\n\nstart_slice = 140\n\npath = \"../input/rsna-2022-cervical-spine-fracture-detection/train_iamges/1.2.826.0.1.3680043.17960/\"\n\n\n# Plot images\nfig, loc = plt.subplots(nrows=3, ncols=3, figsize=(10,10))\nfig.suptitle(f'ID: 1.2.826.0.1.3680043.17960', weight=\"bold\", size=20)\n\nfor i in range(start_slice,start_slice+9):\n    dcm_path = \"../input/rsna-2022-cervical-spine-fracture-detection/train_images/1.2.826.0.1.3680043.17960/{}.dcm\".format(i)\n    example_dcm = pydicom.dcmread(dcm_path)\n    \n    # Calculate coordinates for the image on the grid\n    x = (i-start_slice) // 3\n    y = (i-start_slice) % 3\n\n    loc[x, y].imshow(example_dcm.pixel_array, cmap='bone')\n    loc[x, y].set_title(f\"Slice: {i}\", fontsize=14, weight='bold')\n    loc[x, y].axis('off')","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:29.171117Z","iopub.execute_input":"2022-09-01T04:40:29.171605Z","iopub.status.idle":"2022-09-01T04:40:30.001904Z","shell.execute_reply.started":"2022-09-01T04:40:29.171553Z","shell.execute_reply":"2022-09-01T04:40:30.001076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The output above shows what the images look like. However, they do not containt any information on the location within the spine and therefore, there is no information about which vertebrae is visible in the slice.","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>4.2 Neuroimaging Informatics Technology Initiative(NIfTI)</b></p>\n</div>\n\n\"The main difference between DICOM and NIfTI is that the raw image data in NIfTI is saved as a 3d image, where in DICOM you have 2d image slices. This makes NIFTI more preferable for some machine learning applications over DICOM, because it is modeled as a 3d image.\" [(Taposh Roy - kdnuggets.com)](https://www.kdnuggets.com/2017/07/medical-image-analysis-deep-learning-part-4.html)\n\nFor this challenge we are provided with 87 files (in the folder segmentations) that correspond to one patient each. We can read the .nii files with the [nibabel library](https://nipy.org/nibabel/gettingstarted.html) and can see, that the shape is (height, width, num_images). The number of images corresponds to the number of DICOM images that are provided for the same patient.\n","metadata":{}},{"cell_type":"code","source":"example_path_nii = f\"../input/rsna-2022-cervical-spine-fracture-detection/segmentations/1.2.826.0.1.3680043.17960.nii\"\nnii_example = nib.load(example_path_nii)\ndata = nii_example.get_fdata()\ndata.shape","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:30.002804Z","iopub.execute_input":"2022-09-01T04:40:30.003109Z","iopub.status.idle":"2022-09-01T04:40:31.416098Z","shell.execute_reply.started":"2022-09-01T04:40:30.003081Z","shell.execute_reply":"2022-09-01T04:40:31.414977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\"Please be aware that the NIFTI files consist of segmentation in the sagittal plane, while the DICOM files are in the axial plane. Please use the NIFTI header information to determine the appropriate orientation such that the DICOM images and segmentation match. Otherwise, you run the risk of having the segmentations flipped in the Z axis and mirrored in the X axis.\" [(Harshit Sheoran)](https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/discussion/340612)\n\nTo achieve that we can do as follows (also provided by [(Harshit Sheoran)](https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/discussion/340612)):\n\n","metadata":{}},{"cell_type":"code","source":"data_transposed = data[:, ::-1, ::-1].transpose(2, 1, 0)\ndata_transposed.shape","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:31.417481Z","iopub.execute_input":"2022-09-01T04:40:31.417959Z","iopub.status.idle":"2022-09-01T04:40:31.424706Z","shell.execute_reply.started":"2022-09-01T04:40:31.417895Z","shell.execute_reply":"2022-09-01T04:40:31.423556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"After the operation, the shape is now (num_images, height, width).","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>4.3 Masks</b></p>\n</div>\n\nBelow are the same slices from the same patient as in 4.1 (You can see a side by side comparison in chapter 4.5.). These masks help us identify the location of the vertebrae within the image an can help us determine which vertebra is in the image. ","metadata":{}},{"cell_type":"code","source":"start_slice = 140\n\n# Plot images\nfig, loc = plt.subplots(nrows=3, ncols=3, figsize=(10,10))\nfig.suptitle(f'ID: 1.2.826.0.1.3680043.17960', weight=\"bold\", size=20)\n\nfor i in range(start_slice,start_slice+9):\n    # Calculate coordinates for the image on the grid\n    x = (i-start_slice) // 3\n    y = (i-start_slice) % 3\n\n    loc[x, y].imshow(data_transposed[i], cmap='inferno')\n    loc[x, y].set_title(f\"Slice: {i}\", fontsize=14, weight='bold')\n    loc[x, y].axis('off')","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:31.426332Z","iopub.execute_input":"2022-09-01T04:40:31.426663Z","iopub.status.idle":"2022-09-01T04:40:32.210082Z","shell.execute_reply.started":"2022-09-01T04:40:31.426633Z","shell.execute_reply":"2022-09-01T04:40:32.208888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<hr>\n\nWe have a total of 87 segmentation files (4.31% of the total) but 2019 patients. The implications of that are explained in 4.4 Determining location.","metadata":{}},{"cell_type":"code","source":"_, _, files = next(os.walk(\"../input/rsna-2022-cervical-spine-fracture-detection/segmentations/\"))\nfile_count = len(files)\ntrain_data_len = len(train_data)\npercentage = np.round(file_count/train_data_len*100,2)\n\nprint(f\"Segmentation files: {file_count}\")\nprint(f\"Training examples: {train_data_len}\")\nprint(f\"({percentage}%)\")","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:32.21146Z","iopub.execute_input":"2022-09-01T04:40:32.211804Z","iopub.status.idle":"2022-09-01T04:40:32.229833Z","shell.execute_reply.started":"2022-09-01T04:40:32.211773Z","shell.execute_reply":"2022-09-01T04:40:32.228685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>4.4 Determining location</b></p>\n</div>\n\nFor the submission we not only need to provide whether a patient has a fracture, but also in which vertebrae. Therefore, we must be able to attribute each slice to the corresponding vertebra.\n\nWith the help of the .nii files we can easily determine the location of the the slice. Which means we can determine which vertebra is visible in any given DICOM image. This can be done by evaluating the unique values in the data that we created in 4.2. (provided by [Harshit Sheoran](https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/discussion/340612))\n\n","metadata":{}},{"cell_type":"code","source":"segmentations = nib.load(f\"../input/rsna-2022-cervical-spine-fracture-detection/segmentations/1.2.826.0.1.3680043.10921.nii\").get_fdata()[:, ::-1, ::-1].transpose(2, 1, 0)\nnp.unique(segmentations[199]) # slice 199 corresponds to DICOM Image 200.dcm","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:32.230903Z","iopub.execute_input":"2022-09-01T04:40:32.231208Z","iopub.status.idle":"2022-09-01T04:40:33.885777Z","shell.execute_reply.started":"2022-09-01T04:40:32.23118Z","shell.execute_reply":"2022-09-01T04:40:33.884311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The second value of the array from the output shows which vertebra is in the slice. In this case C6.\n\nUnfortunately, since we only have 87 segmentation files, this doens't scale to the whole training data and we need another solution to determine the location of all other patients. \n\n[Samuel Cortinhas](https://www.kaggle.com/samuelcortinhas) offers an interesting approach to this issue in this notebook:\nhttps://www.kaggle.com/code/samuelcortinhas/extracting-vertebrae-c1-c7/notebook\n","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>4.5 Comparision</b></p>\n</div>\n\nThe comparison of the .dcm file (Train image) with the .nii file (Segmentation Mask) for the same slice of the same patient shows nicely, how usefull the segmentation data is and how easy it is to isolate the vertebra with it.","metadata":{}},{"cell_type":"code","source":"ds = pydicom.dcmread('../input/rsna-2022-cervical-spine-fracture-detection/train_images/1.2.826.0.1.3680043.17960/151.dcm')\nmask = data_transposed[150]\n\nplt.figure(figsize=(15,6))\nplt.subplot(1,2,1)\nplt.imshow(ds.pixel_array, cmap=\"bone\")\nplt.title('Train Image')\nplt.subplot(1,2,2)\nplt.imshow(mask, cmap='inferno')\nplt.title('Segmentation Mask')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:33.88767Z","iopub.execute_input":"2022-09-01T04:40:33.888006Z","iopub.status.idle":"2022-09-01T04:40:34.253098Z","shell.execute_reply.started":"2022-09-01T04:40:33.887976Z","shell.execute_reply":"2022-09-01T04:40:34.25197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Example of fractures\n<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>5.1 Bounding Boxes</b></p>\n</div>\n\nBounding boxes are only provided for patients with fractures, but unfortunately not all of them. Out of 961 patients with fractures, only **235 (24.45%)** are provided with bounding boxes. The total number of bounding boxes is 7217 and there already clear, that one patient has multiple bounding boxes. These bounding boxes show us exactly where the fracture is located and therefore, it would be usefull to have this information for all images with fracture. One consideration is to enhance the training data by first training an **object localization model** in order to provide bounding boxes for the rest of the patients.","metadata":{}},{"cell_type":"code","source":"bbox_len = len(train_bbox)\npatients_with_fracture = train_data[\"patient_overall\"].sum()\npatients_with_bbox = train_bbox[\"StudyInstanceUID\"].unique().size\n\npercentage = np.round(patients_with_bbox/patients_with_fracture*100,2)\n\nprint(f\"Number of bouding boxes: {bbox_len}\")\nprint(f\"Number of Patients: {len(train_data)}\")\nprint(f\"Patients with fracture: {patients_with_fracture}\")\nprint(f\"Patients with bounding boxes: {patients_with_bbox}\")\nprint(f\"({percentage}%)\")","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:43:52.202153Z","iopub.execute_input":"2022-09-01T04:43:52.202514Z","iopub.status.idle":"2022-09-01T04:43:52.210792Z","shell.execute_reply.started":"2022-09-01T04:43:52.202484Z","shell.execute_reply":"2022-09-01T04:43:52.209463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>5.2 Example images</b></p>\n</div>\n\nBelow are examples of bounding boxes on different patients. The code comes from [Samuel Cortinhas](https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda).\n\n**Important:** make sure that you have all the necessary imports in order to correctly display the images (see 1.5 libraries).","metadata":{}},{"cell_type":"code","source":"base_path = \"../input/rsna-2022-cervical-spine-fracture-detection\"\n\ndef plot_fracture(slice_num,bbox_id,ax_id1,ax_id2):\n    file = pydicom.dcmread(f\"{base_path}/train_images/{bbox_id}/{slice_num}.dcm\")\n    img = apply_voi_lut(file.pixel_array, file)\n    info = train_bbox[(train_bbox['StudyInstanceUID']==bbox_id)&(train_bbox['slice_number']==slice_num)]\n    rect = patches.Rectangle((float(info.x), float(info.y)), float(info.width), float(info.height), linewidth=3, edgecolor='r', facecolor='none')\n\n    axes[ax_id1,ax_id2].imshow(img, cmap=\"bone\")\n    axes[ax_id1,ax_id2].add_patch(rect)\n    axes[ax_id1,ax_id2].set_title(f\"ID:{bbox_id}, Slice: {slice_num}\", fontsize=20, weight='bold',y=1.02)\n    axes[ax_id1,ax_id2].axis('off')\n\nfig, axes = plt.subplots(nrows=2, ncols=2, figsize=(18,18))\nplot_fracture(146,'1.2.826.0.1.3680043.10051',0,0)\nplot_fracture(151,'1.2.826.0.1.3680043.10678',0,1)\nplot_fracture(174,'1.2.826.0.1.3680043.10678',1,0)\nplot_fracture(90,'1.2.826.0.1.3680043.10732',1,1)","metadata":{"execution":{"iopub.status.busy":"2022-09-01T04:40:34.270952Z","iopub.execute_input":"2022-09-01T04:40:34.271409Z","iopub.status.idle":"2022-09-01T04:40:35.25738Z","shell.execute_reply.started":"2022-09-01T04:40:34.271365Z","shell.execute_reply":"2022-09-01T04:40:35.256015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 7. References/Acknowledgements\n\n<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>7.1 Acknowledgements</b></p>\n</div>\n\nA very special thanks to [Samuel Cortinhas](https://www.kaggle.com/samuelcortinhas) for the inspiration to create this notebook. Many ideas and also code (always referenced) come from his amazing indepth EDA (https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda) and helped me to understand the challenge as well as all the provided data much better. \n\nThank you to everyone that provided amazing inputs for this notebook. Everyone's code used should be referenced in this notebook at the appropriate position. If you notice any references missing, please do not hesitate to comment and I will gladly add them. :)","metadata":{}},{"cell_type":"markdown","source":"<div style=\"color:white;display:fill;\n            background-color:#48AFFF;font-size:160%;\n            font-family:Arial\">\n    <p style=\"padding: 4px;color:white;\"><b>7.2 References</b></p>\n</div>\n\n* [🦴 RSNA Fracture Detection - in-depth EDA](https://www.kaggle.com/code/samuelcortinhas/rsna-fracture-detection-in-depth-eda) by [Samuel Cortinhas](https://www.kaggle.com/samuelcortinhas).\n* [EDA🔎 | RSNA 2022 Fracture Detection](https://www.kaggle.com/code/pathikghugare/eda-rsna-2022-fracture-detection) by [Pathik Ghugare](https://www.kaggle.com/pathikghugare).\n* [Explaining Data and Submission in detail](https://www.kaggle.com/competitions/rsna-2022-cervical-spine-fracture-detection/discussion/340612) by [Harshit Sheoran](https://www.kaggle.com/harshitsheoran)\n* [Pydicom Utility](https://www.kaggle.com/datasets/ipythonx/for-pydicom) by [M.Innat](https://www.kaggle.com/ipythonx/datasets)","metadata":{}}]}