{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# RSNA Lumbar Spine Challenge\nAuthors: Abhinav Suri MPH, Andrew Wentland MD PhD, Hari Trivedi MD \n– Radiology Artificial Intelligence Data Standards Committee","metadata":{}},{"cell_type":"markdown","source":"### Purpose of this notebook:\n\nThis notebook aims to give a brief overview of what data is available in the challenge and how to get started with visualizing some of the conditions in our dataset. ","metadata":{}},{"cell_type":"markdown","source":"### Overview of the clinical problem\n\nDegenerative spine conditions adversely affect people’s quality of life. Detecting these conditions is crucial for determining therapeutic plans for patients. Therefore, it is essential to develop methods for detecting and assessing the severity of degenerative spine conditions on imaging.\n \nThis challenge primarily focuses on identifying three types of conditions in the lumbar region of the spine (refer below for the anatomical overview). The three conditions we aim to assess are:\n \n1. Foraminal narrowing (on either the left or right foramen at a specified level).\n2. Subarticular stenosis (on either the left or right side at a specified level).\n3. Canal stenosis (only at a specified level).\n \nEach of these conditions can manifest at various levels within the spine itself, specifically at each vertebral disc (e.g., L4/5 corresponds to the vertebral disc between the L4 and L5 vertebral bodies).\n\n\nFor each of the conditions, you'll need to predict whether the degree of compression is normal/mild, moderate, or severe. You can refer to the example test submission `sample_submission.csv` to get a better idea for what we're looking for in terms of output. For each case, you'll have to output a score from 0 to 1 representing the probability of the patient having a specific grade (`normal_mild`, `moderate`, `severe`), at the spinal level (`l1_l2`, `l2_l3`, `l3_l4`, `l4_l5`, `l5_s1`), for that condition (`spinal_canal_stenosis`, `left_neural_foraminal_narrowing`, `right_neural_foraminal_narrowing`, `left_subarticular_stenosis`, `right_subarticular_stenosis`):\n\n\nLet's talk a bit about the anatomy to get a sense for what we're asking you all to detect.\n\n### Anatomical Overview\n\nThe spine is divided into four regions: the cervical region (with 7 vertebral bodies), the thoracic region (with 12 vertebral bodies), the lumbar region (with 5 vertebral bodies), and the sacral region (with 3-5 fused vertebral bodies). \n\n<img src=\"https://prod-images-static.radiopaedia.org/images/53655832/Gray-square.001_big_gallery.jpeg\" width=400/>\n\n*From [Radiopedia](https://prod-images-static.radiopaedia.org/images/53655832/Gray-square.001_big_gallery.jpeg)*\n\nBetween each vertebral body in all of the regions (except the sacrum) is a vertebral disc. Furthermore, along the posterior aspect of each vertebral body lies the spinal cord. At each vertebral body, spinal nerves leave the spinal cord through openings between vertebral bodies called foramina.\n\n<img src=\"https://files.miamineurosciencecenter.com/media/filer_public_thumbnails/filer_public/78/1e/781e78be-8980-466f-8a82-83a5c8350770/herniated_disc_larger.jpg__720.0x600.0_q85_subject_location-360%2C300_subsampling-2.jpg\" width=400/>  \n\n*From [Miami Neuroscience Center](https://miamineurosciencecenter.com/en/conditions/herniated-disc/)*\n\nCompression of the spinal cord or any of the nerves can cause pain to patients. Things that can cause compression of these nerves/the spinal cord include a bulging vertebral disc, degenerative changes in the bones itself (leading them to grow protrusions/become compressed), trauma, or thickening of the ligaments surrounding the spinal cord.\n\n### Foraminal Narrowing Overview\n\nThe spinal cord has spinal nerves that exit the spinal canal through openings called foramina. The foramina are best viewed in the sagittal plane. Sometimes these openings can become compressed, resulting in foraminal narrowing. This compression results in pain for patients along the nerve distribution that is downstream of the compression. \n\nOn the left, the image shows a sagittal MR slice where the foramina are visible. Crosshairs show where the foramina exit the spinal canal. On the right, the image shows our grading criteria for designating the degree of compression (note for this challenge, Normal/Mild is one label).\n<p float=\"middle\">\n<img src=\"https://i.imgur.com/6c7erNM.png\" width=300/>\n<img src=\"https://i.imgur.com/b1VGiN5.png\" width=300/>\n</p>\n\n### Subarticular Stenosis Overview\n\nSubarticular stenosis is due to compression of the spinal cord in the subarticular zone (this compression can be best visualized in the axial plane).\n\nOn the left is a schematic showing the relevant anatomical zone. On the right is our grading criteria for designating the degree of subarticular stenosis (normal/mild is collapsed into one label for this challenge). \n<p float=\"middle\">\n<img src=\"https://files.miamineurosciencecenter.com/media/filer_public_thumbnails/filer_public/d5/08/d508ae6a-a4f2-4796-be9f-455f8df45fe1/herniation_zones.jpg__1700.0x1308.0_q85_subject_location-850%2C656_subsampling-2.jpg\" width=300/>\n<img src=\"https://i.imgur.com/Usuxgge.png\" width=300/>\n</p>\n\n*Left image from [Miami Neuroscience Center](https://miamineurosciencecenter.com/en/conditions/herniated-disc/)*\n\n\n### Canal Stenosis Overview\n\nCanal stenosis is impingement on the spinal canal (where the spinal cord travels). Impingement can be due to a bulging vertebral disc, trauma, bony osteophytes (outgrowths of the vertebral bodies due to degenerative changes), or ligamental thickening (of the ligaments that run along the length of the spinal canal). The degree of compression is best assessed in the axial plane.\n\nOn the left, we show canal stenosis visible in the sagittal plane (to give an overview of what it looks like). On the right, we show our canal stenosis grading criteria (normal/mild are collapsed into one label). \n\n<p float=\"middle\">\n<img src=\"https://prod-images-static.radiopaedia.org/images/940993/f7a8adca63efae788f621869cc21e8_big_gallery.jpg\" width=300/>\n<img src=\"https://i.imgur.com/opjnAwl.png\" width=300/>\n</p>\n\n*From [Radiopedia](https://prod-images-static.radiopaedia.org/images/940993/f7a8adca63efae788f621869cc21e8_big_gallery.jpg)*\n\n### Imaging Overview\n\nMRI imaging of the spine can be taken in three planes: the axial plane, the sagittal plane, and the coronal plane. The two main image types you'll need for this challenge are the axial and sagittal planes. The axial plane takes images horizonal slices (perpendicular to the spine) across the body from top to bottom. The sagittal plane takes vertical slices (parallel to the spine) going from left to right. \n\nMRI images come in multiple variants. They can generally be classified as either being T1 weighted or T2 weighted. T1 weighted images show fat as being brighter. The inner part of bones would appear brighter on T1 images. T2 images show water as brighter. The spinal canal would appear as brighter on T2 images. MRI images are not standardized with regards to the pixel values that are output from it (unlike CT images). So you'll need to figure out how to standardize these images (or maybe you wont need to at all, we'll leave it up to you). ","metadata":{"jp-MarkdownHeadingCollapsed":true}},{"cell_type":"markdown","source":"## Expected Directory Structure\nWe expect the following to be in your working directory to run this notebook.\n\n```\n.\n├── ExploreData.ipynb **This notebook\n└── /kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/\n    ├── test_images/\n    │   ├── 1005139/\n    │   │   └── 609308237/\n    │   │       ├── 1.dcm\n    │   │       └── ...\n    │   └── ...\n    ├── test_series_descriptions.csv\n    ├── train_images/\n    │   ├── 4003253/\n    │   │   └── 702807833/\n    │   │       ├── 1.dcm\n    │   │       └── ...\n    │   └── ...\n    ├── train_label_coordinates.csv\n    ├── train_series_descriptions.csv\n    └── train.csv\n```","metadata":{}},{"cell_type":"markdown","source":"## Loading Diagnosis Information","metadata":{}},{"cell_type":"markdown","source":"In this part of the notebook, we'll load in information about the diagnoses present in our dataset to give an overview of the distribution of cases.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport pydicom\nimport numpy as np\nimport os\nimport glob\nfrom tqdm import tqdm\nimport warnings","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:05.022080Z","iopub.execute_input":"2024-05-17T21:26:05.022692Z","iopub.status.idle":"2024-05-17T21:26:05.989779Z","shell.execute_reply.started":"2024-05-17T21:26:05.022628Z","shell.execute_reply":"2024-05-17T21:26:05.988632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:05.991937Z","iopub.execute_input":"2024-05-17T21:26:05.992462Z","iopub.status.idle":"2024-05-17T21:26:06.033379Z","shell.execute_reply.started":"2024-05-17T21:26:05.992421Z","shell.execute_reply":"2024-05-17T21:26:06.032103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Total Cases: \", len(train))","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:06.036437Z","iopub.execute_input":"2024-05-17T21:26:06.036902Z","iopub.status.idle":"2024-05-17T21:26:06.045562Z","shell.execute_reply.started":"2024-05-17T21:26:06.036862Z","shell.execute_reply":"2024-05-17T21:26:06.044266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.columns","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:06.049021Z","iopub.execute_input":"2024-05-17T21:26:06.049920Z","iopub.status.idle":"2024-05-17T21:26:06.073740Z","shell.execute_reply.started":"2024-05-17T21:26:06.049877Z","shell.execute_reply":"2024-05-17T21:26:06.071345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"figure, axis = plt.subplots(1,3, figsize=(20,5)) \nfor idx, d in enumerate(['foraminal', 'subarticular', 'canal']):\n    diagnosis = list(filter(lambda x: x.find(d) > -1, train.columns))\n    dff = train[diagnosis]\n    with warnings.catch_warnings():\n        warnings.simplefilter(action='ignore', category=FutureWarning)\n        value_counts = dff.apply(pd.value_counts).fillna(0).T\n    value_counts.plot(kind='bar', stacked=True, ax=axis[idx])\n    axis[idx].set_title(f'{d} distribution')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:06.075232Z","iopub.execute_input":"2024-05-17T21:26:06.076542Z","iopub.status.idle":"2024-05-17T21:26:07.637710Z","shell.execute_reply.started":"2024-05-17T21:26:06.076496Z","shell.execute_reply":"2024-05-17T21:26:07.636339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As expected many of our patients have normal/mild grades for each of the diagnoses categories. You'll also see that for some of the diagnoses (particularly subarticular stenosis category), there are missing data. This is due to the fact that some of the images do not have those regions visualized (more specifically the most superior vertebral bodies were less likely to make it into the imaging field).","metadata":{}},{"cell_type":"markdown","source":"## Loading in images","metadata":{}},{"cell_type":"markdown","source":"Now that we can see the rough distribution of diagnoses, let's go ahead and load in an example set of scans for one patient. We'll start off by grabbing the scan for one patient as an example. \n\nIn terms of background. Each patient has a Study (called a StudyInstanceUID). That study has multiple series called a (SeriesInstanceUID). Within a series you have multiple images with a unique SOPInstanceUID. \n\nAll of this data is tied together via the csv from earlier that listed diagnoses types, but also a separate dicom metadata file that contains information about the particular series descriptions (containing useful series descriptions such as whether the image is sagital or axial and t1 vs t2). Though the names for the series descriptions are not standardized.","metadata":{}},{"cell_type":"markdown","source":"### Grab metadata for each scan.\nFor each scan let's create an object with the following structure:\n\n```\nmeta_obj = {\n    StudyInstanceUID: {\n        'folder_path': ... # path to the folder,\n        'SeriesInstanceUIDs': [ Array of the SeriesInstanceUIDs ],\n        'SeriesDescriptions' [ Array of the Series Descriptions ]\n    }, ...\n}\n```","metadata":{}},{"cell_type":"code","source":"# List out all of the Studies we have on patients.\npart_1 = os.listdir('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images')\npart_1 = list(filter(lambda x: x.find('.DS') == -1, part_1))","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:07.639435Z","iopub.execute_input":"2024-05-17T21:26:07.639847Z","iopub.status.idle":"2024-05-17T21:26:07.780321Z","shell.execute_reply.started":"2024-05-17T21:26:07.639811Z","shell.execute_reply":"2024-05-17T21:26:07.778712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_meta_f = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_series_descriptions.csv')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:07.782048Z","iopub.execute_input":"2024-05-17T21:26:07.782428Z","iopub.status.idle":"2024-05-17T21:26:07.800098Z","shell.execute_reply.started":"2024-05-17T21:26:07.782396Z","shell.execute_reply":"2024-05-17T21:26:07.798835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"p1 = [(x, f\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/{x}\") for x in part_1]\nmeta_obj = { p[0]: { 'folder_path': p[1], \n                    'SeriesInstanceUIDs': [] \n                   } \n            for p in p1 }","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:07.801669Z","iopub.execute_input":"2024-05-17T21:26:07.804348Z","iopub.status.idle":"2024-05-17T21:26:07.813493Z","shell.execute_reply.started":"2024-05-17T21:26:07.804305Z","shell.execute_reply":"2024-05-17T21:26:07.812010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for m in meta_obj:\n    meta_obj[m]['SeriesInstanceUIDs'] = list(\n        filter(lambda x: x.find('.DS') == -1, \n               os.listdir(meta_obj[m]['folder_path'])\n              )\n    )","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:07.814657Z","iopub.execute_input":"2024-05-17T21:26:07.814962Z","iopub.status.idle":"2024-05-17T21:26:12.810369Z","shell.execute_reply.started":"2024-05-17T21:26:07.814936Z","shell.execute_reply":"2024-05-17T21:26:12.809342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# grabs the correspoding series descriptions\nfor k in tqdm(meta_obj):\n    for s in meta_obj[k]['SeriesInstanceUIDs']:\n        if 'SeriesDescriptions' not in meta_obj[k]:\n            meta_obj[k]['SeriesDescriptions'] = []\n        try:\n            meta_obj[k]['SeriesDescriptions'].append(\n                df_meta_f[(df_meta_f['study_id'] == int(k)) & \n                (df_meta_f['series_id'] == int(s))]['series_description'].iloc[0])\n        except:\n            print(\"Failed on\", s, k)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:12.813644Z","iopub.execute_input":"2024-05-17T21:26:12.813952Z","iopub.status.idle":"2024-05-17T21:26:16.439403Z","shell.execute_reply.started":"2024-05-17T21:26:12.813926Z","shell.execute_reply":"2024-05-17T21:26:16.438133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_obj[list(meta_obj.keys())[1]]","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:16.441265Z","iopub.execute_input":"2024-05-17T21:26:16.441723Z","iopub.status.idle":"2024-05-17T21:26:16.448808Z","shell.execute_reply.started":"2024-05-17T21:26:16.441684Z","shell.execute_reply":"2024-05-17T21:26:16.447912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Pull up images for one patient","metadata":{}},{"cell_type":"markdown","source":"Now that we've made our meta obj, let's pull up all the images for one patient.","metadata":{}},{"cell_type":"code","source":"patient = train.iloc[1]","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:16.449771Z","iopub.execute_input":"2024-05-17T21:26:16.450221Z","iopub.status.idle":"2024-05-17T21:26:16.462233Z","shell.execute_reply.started":"2024-05-17T21:26:16.450085Z","shell.execute_reply":"2024-05-17T21:26:16.460927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ptobj = meta_obj[str(patient['study_id'])]","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:16.463900Z","iopub.execute_input":"2024-05-17T21:26:16.464353Z","iopub.status.idle":"2024-05-17T21:26:16.474144Z","shell.execute_reply.started":"2024-05-17T21:26:16.464313Z","shell.execute_reply":"2024-05-17T21:26:16.472856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(ptobj)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:16.475329Z","iopub.execute_input":"2024-05-17T21:26:16.475629Z","iopub.status.idle":"2024-05-17T21:26:16.486853Z","shell.execute_reply.started":"2024-05-17T21:26:16.475604Z","shell.execute_reply":"2024-05-17T21:26:16.485147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get data into the format\n\"\"\"\nim_list_dcm = {\n    '{SeriesInstanceUID}': {\n        'images': [\n            {'SOPInstanceUID': ...,\n             'dicom': PyDicom object\n            },\n            ...,\n        ],\n        'description': # SeriesDescription\n    },\n    ...\n}\n\"\"\"\nim_list_dcm = {}\nfor idx, i in enumerate(ptobj['SeriesInstanceUIDs']):\n    im_list_dcm[i] = {'images': [], 'description': ptobj['SeriesDescriptions'][idx]}\n    images = glob.glob(f\"{ptobj['folder_path']}/{ptobj['SeriesInstanceUIDs'][idx]}/*.dcm\")\n    for j in sorted(images, key=lambda x: int(x.split('/')[-1].replace('.dcm', ''))):\n        im_list_dcm[i]['images'].append({\n            'SOPInstanceUID': j.split('/')[-1].replace('.dcm', ''), \n            'dicom': pydicom.dcmread(j) })","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:16.488142Z","iopub.execute_input":"2024-05-17T21:26:16.489654Z","iopub.status.idle":"2024-05-17T21:26:17.020913Z","shell.execute_reply.started":"2024-05-17T21:26:16.489618Z","shell.execute_reply":"2024-05-17T21:26:17.019715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to display images\ndef display_images(images, title, max_images_per_row=4):\n    # Calculate the number of rows needed\n    num_images = len(images)\n    num_rows = (num_images + max_images_per_row - 1) // max_images_per_row  # Ceiling division\n\n    # Create a subplot grid\n    fig, axes = plt.subplots(num_rows, max_images_per_row, figsize=(5, 1.5 * num_rows))\n    \n    # Flatten axes array for easier looping if there are multiple rows\n    if num_rows > 1:\n        axes = axes.flatten()\n    else:\n        axes = [axes]  # Make it iterable for consistency\n\n    # Plot each image\n    for idx, image in enumerate(images):\n        ax = axes[idx]\n        ax.imshow(image, cmap='gray')  # Assuming grayscale for simplicity, change cmap as needed\n        ax.axis('off')  # Hide axes\n\n    # Turn off unused subplots\n    for idx in range(num_images, len(axes)):\n        axes[idx].axis('off')\n    fig.suptitle(title, fontsize=16)\n\n    plt.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:17.022403Z","iopub.execute_input":"2024-05-17T21:26:17.022819Z","iopub.status.idle":"2024-05-17T21:26:17.038643Z","shell.execute_reply.started":"2024-05-17T21:26:17.022780Z","shell.execute_reply":"2024-05-17T21:26:17.036577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in im_list_dcm:\n    display_images([x['dicom'].pixel_array for x in im_list_dcm[i]['images']], \n                   im_list_dcm[i]['description'])","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:17.039674Z","iopub.execute_input":"2024-05-17T21:26:17.039981Z","iopub.status.idle":"2024-05-17T21:26:23.184612Z","shell.execute_reply.started":"2024-05-17T21:26:17.039956Z","shell.execute_reply":"2024-05-17T21:26:23.183443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Look at the coordinates of pathologies\n\nWe can also display the coordinates of the pathologies that are annotated for each of the patients.","metadata":{}},{"cell_type":"code","source":"df_coor = pd.read_csv('/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:23.186143Z","iopub.execute_input":"2024-05-17T21:26:23.186512Z","iopub.status.idle":"2024-05-17T21:26:23.296034Z","shell.execute_reply.started":"2024-05-17T21:26:23.186480Z","shell.execute_reply":"2024-05-17T21:26:23.294836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_coor.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:23.297878Z","iopub.execute_input":"2024-05-17T21:26:23.298661Z","iopub.status.idle":"2024-05-17T21:26:23.317481Z","shell.execute_reply.started":"2024-05-17T21:26:23.298615Z","shell.execute_reply":"2024-05-17T21:26:23.316138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display_coor_on_img(c, i, title):\n    center_coordinates = (int(c['x']), int(c['y']))\n    radius = 10\n    color = (255, 0, 0)  # Red color in BGR\n    thickness = 2\n    IMG = i['dicom'].pixel_array\n    IMG_normalized = cv2.normalize(IMG, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)\n    \n    IMG_with_circle = cv2.circle(IMG_normalized.copy(), center_coordinates, radius, color, thickness)\n    \n    # Convert the image from BGR to RGB for correct color display in matplotlib\n    IMG_with_circle = cv2.cvtColor(IMG_with_circle, cv2.COLOR_BGR2RGB)\n    \n    # Display the image\n    plt.imshow(IMG_with_circle)\n    plt.axis('off')  # Turn off axis numbers and ticks\n    plt.title(title)\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:23.319136Z","iopub.execute_input":"2024-05-17T21:26:23.319521Z","iopub.status.idle":"2024-05-17T21:26:23.326974Z","shell.execute_reply.started":"2024-05-17T21:26:23.319481Z","shell.execute_reply":"2024-05-17T21:26:23.326005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"coor_entries = df_coor[df_coor['study_id'] == int(patient['study_id'])]","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:23.328222Z","iopub.execute_input":"2024-05-17T21:26:23.328707Z","iopub.status.idle":"2024-05-17T21:26:23.340118Z","shell.execute_reply.started":"2024-05-17T21:26:23.328680Z","shell.execute_reply":"2024-05-17T21:26:23.339056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Only showing severe cases for this patient\")\nfor idc, c in coor_entries.iterrows():\n    for i in im_list_dcm[str(c['series_id'])]['images']:\n        if int(i['SOPInstanceUID']) == int(c['instance_number']):\n            try:\n                patient_severity = patient[\n                    f\"{c['condition'].lower().replace(' ', '_')}_{c['level'].lower().replace('/', '_')}\"\n                ]\n            except Exception as e:\n                patient_severity = \"unknown severity\"\n            title = f\"{i['SOPInstanceUID']} \\n{c['level']}, {c['condition']}: {patient_severity} \\n{c['x']}, {c['y']}\"\n            if patient_severity == 'Severe':\n                display_coor_on_img(c, i, title)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T21:26:23.341469Z","iopub.execute_input":"2024-05-17T21:26:23.341822Z","iopub.status.idle":"2024-05-17T21:26:23.816492Z","shell.execute_reply.started":"2024-05-17T21:26:23.341794Z","shell.execute_reply":"2024-05-17T21:26:23.815345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Wrap up","metadata":{}},{"cell_type":"markdown","source":"In this notebook we covered the basic distribution of cases in our popuation, how to look at which scans and diagnoses correspond to each patient, and how to visualize the patient DICOMs + locations of annotated pathologies. Have fun with the challenge!","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}