{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"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":"Published on May 17, 2024. By Marília Prata, mpwolke","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-05-17T16:24:25.596828Z","iopub.execute_input":"2024-05-17T16:24:25.597278Z","iopub.status.idle":"2024-05-17T16:26:17.149215Z","shell.execute_reply.started":"2024-05-17T16:24:25.597245Z","shell.execute_reply":"2024-05-17T16:26:17.147744Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"![](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3__mGZDdW3Tqxr6YPClYU9H31uymAQk_LVkKeHMjQng&s)https://www.curevision.ca/blog-detail/en/what-is-the-importance-of-dicom-for-healthcare-facilities","metadata":{}},{"cell_type":"markdown","source":"#Competition Citation\n\n@misc{rsna-2024-lumbar-spine-degenerative-classification,\n\n    author = {Chris Carr, Errol Colak, HCL-Jevster, John Mongan, Luciano Prevedello, Maggie, Maryam Vazirabad, Michelle Riopel, Robyn Ball},\n    \n    title = {RSNA 2024 Lumbar Spine Degenerative Classification},\n    \n    publisher = {Kaggle},\n    year = {2024},\n    url = {https://kaggle.com/competitions/rsna-2024-lumbar-spine-degenerative-classification}","metadata":{}},{"cell_type":"markdown","source":"![](https://columbusspine.com/wp-content/uploads/2017/08/ddd-600.jpg)https://columbusspine.com/degenerative-disc-disease-in-cervical-lumbar-spine-could-benefit-from-spinal-decompression-therapy-in-columbus-ohio/","metadata":{}},{"cell_type":"markdown","source":"#Ready to work with Dicoms \n\nWorking with Dicoms\n\n[OsiriX Dicom Viewer](https://www.osirix-viewer.com/)\n\n[Pydicom](https://pydicom.github.io/pydicom/stable/)\n\n[Pydicom documentation](https://pydicom.github.io/pydicom/0.9/)\n\n[Oro Dicom](https://cran.r-project.org/web/packages/oro.dicom/index.html)A package for working with images in R.\n\n[Mango: A viewer for medical research images.](https://mangoviewer.com/)\n\nDeep Learning for MRI\n\nBy Jason A. Polzin\n\nSteps:\n\n\"Image quality inspection: In the first step, the author checked if the given localizer image is suitable to identify the plane for the desired anatomy. This is achieved by using a fiver layer, dyadic reduction regular CNN classification network model (that we call “LocalizerIQ-Net”) to identify slices with relevant anatomy, slices with artifacts and irrelevant slices. If the localizer image is not suitable for ISP, relevant feedback is provided to the scan operator. They used the built-in TensorFlow functions for image manipulation to achieve data augmentation during the training of LocalizerIQ-Net.\"\n\n\"Identification of anatomy coverage: Next, the author located the spatial-extent of the desired anatomy in the localizer images by incorporating a shape-based semantic image segmentation U-Net DL model (called “Coverage-Net”). This helps the next processing steps to be robust to changes in imaging parameter settings across hospitals and clinics as well as changes in shapes and sizes of the patient’s anatomy.\"\n\n\"Identification of precise plane orientation and location: For each desired anatomic structure, the author found the scan-plane that is best suited to image that structure using one or more image segmentation 3D U-Net models (called “Orientation-Net”). Orientation-Net directly segments the desired-planes on localizer images, which is then used to compute the orientation and location.\"\n\n\"The entire process took ~3.5 seconds on a high-performance CPU. The training and testing data for these DL models came from more than 1300 subjects and were acquired using various GE scanner models and field strengths from several clinical sites.\"\n\nhttps://blog.tensorflow.org/2019/03/intelligent-scanning-using-deep-learning.html\n\nBuilding Neural Network for Medical Imaging using Deep Learning in Tensorflow \n\nBy Chandan Verma\n\nSteps below were taken in order to make the data consumable by the CNN:\n\nLoading the Dicom Image, Converting the Pixel values to Hounsfield(HU) units,\nResampling, ROI Generation, Normalization, Zero Centering, Resizing the data\nSplitting the data and label and Creating the Convolutional neural network.\"\n\nConverting Pixel values to Hounsfield units(HU\n\n\"Converting Pixel values to Hounsfield units(HU): This helps us in segregating different parts of the body. Converting to Hounsfield units enable us to extract the lungs which is the area of interest to us in this case. More on Hounsfield units(HU) here. Below is the formula to compute HU from pixel values.\"\n\nhu = pixel_value * slope + intercept\n  \n  \nhttps://medium.com/@verma.chandan/building-neural-network-for-medical-imaging-using-deep-learning-in-tensorflow-part-1-ab993b7fb04f  \n\n\n#Kaggle Inspiration:\n\n[Data Science Bowl 2017](https://www.kaggle.com/competitions/data-science-bowl-2017/overview) In this Competition dataset, you are given over a thousand low-dose CT images from high-risk patients in DICOM format.\n\n[DON'T see like a radiologist! -fastai](https://www.kaggle.com/code/jhoward/don-t-see-like-a-radiologist-fastai) By Jeremy Howard 5y ago\n\n[Basic EDA + Data Visualization](https://www.kaggle.com/code/marcovasquez/basic-eda-data-visualization/notebook) By Marco Vasquez E. - 5y ago\n\n[Standardizing Unusual Dicoms](https://www.kaggle.com/competitions/rsna-2023-abdominal-trauma-detection/discussion/427217) By Hui Ming Lin","metadata":{}},{"cell_type":"code","source":"import glob, pylab, pandas as pd\nimport pydicom, numpy as np\nfrom os import listdir\nfrom os.path import isfile, join\nimport matplotlib.pylab as plt\nimport os\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:57:33.958593Z","iopub.execute_input":"2024-05-17T16:57:33.959147Z","iopub.status.idle":"2024-05-17T16:57:34.961056Z","shell.execute_reply.started":"2024-05-17T16:57:33.959100Z","shell.execute_reply":"2024-05-17T16:57:34.959919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv('../input/rsna-2024-lumbar-spine-degenerative-classification/train.csv')\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:50:32.248137Z","iopub.execute_input":"2024-05-17T16:50:32.248584Z","iopub.status.idle":"2024-05-17T16:50:32.323218Z","shell.execute_reply.started":"2024-05-17T16:50:32.248549Z","shell.execute_reply":"2024-05-17T16:50:32.321425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Checking one Stenosis Severity Level","metadata":{}},{"cell_type":"code","source":"#By Rob Mulla https://www.kaggle.com/code/robikscube/sign-language-recognition-eda-twitch-stream\n\nfig, ax = plt.subplots(figsize=(4, 4))\ntrain[\"right_subarticular_stenosis_l5_s1\"].value_counts().head().sort_values(ascending=True).plot(\n    kind=\"barh\", color='purple', ax=ax, title=\"Right Subarticular Stenosis Severity Level\"\n)\nax.set_xlabel(\"Number of Training Examples\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2024-05-17T17:38:44.568190Z","iopub.execute_input":"2024-05-17T17:38:44.568826Z","iopub.status.idle":"2024-05-17T17:38:44.770065Z","shell.execute_reply.started":"2024-05-17T17:38:44.568782Z","shell.execute_reply":"2024-05-17T17:38:44.768167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label = pd.read_csv('../input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv')\nlabel.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:18:52.516235Z","iopub.execute_input":"2024-05-17T17:18:52.516716Z","iopub.status.idle":"2024-05-17T17:18:52.651386Z","shell.execute_reply.started":"2024-05-17T17:18:52.516681Z","shell.execute_reply":"2024-05-17T17:18:52.649761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['right_subarticular_stenosis_l5_s1'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:34:00.574064Z","iopub.execute_input":"2024-05-17T17:34:00.574528Z","iopub.status.idle":"2024-05-17T17:34:00.586127Z","shell.execute_reply.started":"2024-05-17T17:34:00.574493Z","shell.execute_reply":"2024-05-17T17:34:00.584601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#By Marco Vasquez E https://www.kaggle.com/code/marcovasquez/basic-eda-data-visualization/notebook\n\nprint('Total File sizes')\nfor f in os.listdir('../input/rsna-2024-lumbar-spine-degenerative-classification'):\n    if 'zip' not in f:\n        print(f.ljust(30) + str(round(os.path.getsize('../input/rsna-2024-lumbar-spine-degenerative-classification/' + f) / 1000000, 2)) + 'MB')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:52:20.274319Z","iopub.execute_input":"2024-05-17T16:52:20.274797Z","iopub.status.idle":"2024-05-17T16:52:20.286889Z","shell.execute_reply.started":"2024-05-17T16:52:20.274762Z","shell.execute_reply":"2024-05-17T16:52:20.285321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Train images ","metadata":{}},{"cell_type":"code","source":"#Code by Abdul Basit https://www.kaggle.com/code/abdulbasitniazi/enetb7-explained-98-fine-tuning-eda\n\ntrain_images = glob.glob('../input/rsna-2024-lumbar-spine-degenerative-classification/train_images/**/*/*.dcm')\nprint(\"Total number of images: \", len(train_images))\n\ntrain_images = pd.Series(train_images)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:08:53.307819Z","iopub.execute_input":"2024-05-17T17:08:53.308950Z","iopub.status.idle":"2024-05-17T17:08:58.540375Z","shell.execute_reply.started":"2024-05-17T17:08:53.308908Z","shell.execute_reply":"2024-05-17T17:08:58.538441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Dicom images overview","metadata":{}},{"cell_type":"code","source":"#By Marco Vasquez E https://www.kaggle.com/code/marcovasquez/basic-eda-data-visualization/notebook\n\nfig=plt.figure(figsize=(15, 10))\ncolumns = 5; rows = 4\nfor i in range(1, columns*rows +1):\n    ds = pydicom.dcmread(train_images[i])#Original was dcmread(train_images_dir + train_images[i])\n    fig.add_subplot(rows, columns, i)\n    plt.imshow(ds.pixel_array, cmap=plt.cm.bone)\n    fig.add_subplot","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:11:19.198264Z","iopub.execute_input":"2024-05-17T17:11:19.198720Z","iopub.status.idle":"2024-05-17T17:11:22.934663Z","shell.execute_reply.started":"2024-05-17T17:11:19.198681Z","shell.execute_reply":"2024-05-17T17:11:22.933463Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#File type of image","metadata":{}},{"cell_type":"code","source":"print(ds) # this is file type of image","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:13:21.211639Z","iopub.execute_input":"2024-05-17T17:13:21.212152Z","iopub.status.idle":"2024-05-17T17:13:21.222154Z","shell.execute_reply.started":"2024-05-17T17:13:21.212113Z","shell.execute_reply":"2024-05-17T17:13:21.220868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"im = ds.pixel_array\nprint(type(im))\nprint(im.dtype)\nprint(im.shape)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:14:03.369462Z","iopub.execute_input":"2024-05-17T17:14:03.369962Z","iopub.status.idle":"2024-05-17T17:14:03.378507Z","shell.execute_reply.started":"2024-05-17T17:14:03.369924Z","shell.execute_reply":"2024-05-17T17:14:03.376884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#By Rob Mulla https://www.kaggle.com/code/robikscube/sign-language-recognition-eda-twitch-stream\n\nfig, ax = plt.subplots(figsize=(4, 4))\nlabel[\"condition\"].value_counts().head().sort_values(ascending=True).plot(\n    kind=\"barh\", color='g', ax=ax, title=\"Lumbar Spine Degenerative Conditions\"\n)\nax.set_xlabel(\"Number of Training Examples\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:25:12.626194Z","iopub.execute_input":"2024-05-17T17:25:12.627693Z","iopub.status.idle":"2024-05-17T17:25:12.883006Z","shell.execute_reply.started":"2024-05-17T17:25:12.627603Z","shell.execute_reply":"2024-05-17T17:25:12.881650Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#By Rob Mulla https://www.kaggle.com/code/robikscube/sign-language-recognition-eda-twitch-stream\n\nfig, ax = plt.subplots(figsize=(4, 4))\nlabel[\"level\"].value_counts().head().sort_values(ascending=True).plot(\n    kind=\"barh\", color='r', ax=ax, title=\"Lumbar Spine Degeneration Level\"\n)\nax.set_xlabel(\"Number of Training Examples\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:32:20.072946Z","iopub.execute_input":"2024-05-17T17:32:20.073429Z","iopub.status.idle":"2024-05-17T17:32:20.271951Z","shell.execute_reply.started":"2024-05-17T17:32:20.073395Z","shell.execute_reply":"2024-05-17T17:32:20.270606Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#The first DICOM image, let's use the pylab.imshow() method:","metadata":{}},{"cell_type":"code","source":"#Marco Vasquez E https://www.kaggle.com/code/marcovasquez/basic-eda-data-visualization/notebook\n\npylab.imshow(im, cmap=pylab.cm.gist_gray)\npylab.axis('on')","metadata":{"execution":{"iopub.status.busy":"2024-05-17T17:28:46.860758Z","iopub.execute_input":"2024-05-17T17:28:46.861281Z","iopub.status.idle":"2024-05-17T17:28:47.198514Z","shell.execute_reply.started":"2024-05-17T17:28:46.861242Z","shell.execute_reply":"2024-05-17T17:28:47.197342Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nfrom matplotlib import pyplot as plt\nimport pydicom\nimport os","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:28:48.951868Z","iopub.execute_input":"2024-05-17T16:28:48.952315Z","iopub.status.idle":"2024-05-17T16:28:49.174091Z","shell.execute_reply.started":"2024-05-17T16:28:48.952285Z","shell.execute_reply":"2024-05-17T16:28:49.173120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Dicom to Coronal view","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#one series from one exam\ndn = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/1004726367/992525108'\n\n#get filenames\nim_list = []\nfor dirname, _, filenames in os.walk(dn):\n    for filename in filenames:\n        im_list.append(os.path.join(dirname, filename))\n\n#sort\nim_list.sort(key = lambda o: int(o.split('/')[-1][:-4]))\nlen(im_list)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:31:38.752408Z","iopub.execute_input":"2024-05-17T16:31:38.752870Z","iopub.status.idle":"2024-05-17T16:31:38.767807Z","shell.execute_reply.started":"2024-05-17T16:31:38.752838Z","shell.execute_reply":"2024-05-17T16:31:38.766166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Convert Dicom functions","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#Read dicom (includes standardization by @HuiMingLin)\ndef dcmread_to_array(fn):\n    dcm = pydicom.dcmread(fn)\n    return dcm_to_array(dcm) \n\ndef dcm_to_array(dcm, width = None, level = None, scaled = True):\n    if dcm.PixelRepresentation == 1:\n        bit_shift = dcm.BitsAllocated - dcm.BitsStored\n        dtype = pixel_array.dtype \n        new_array = (pixel_array << bit_shift).astype(dtype) >>  bit_shift\n        arr = pydicom.pixel_data_handlers.util.apply_modality_lut(new_array, dcm)\n    else:\n        arr = dcm.pixel_array.astype('float32')\n    #slope, intercept\n    slope = 1\n    intercept = 0\n    if \"RescaleIntercept\" in dcm and \"RescaleSlope\" in dcm:\n        intercept = float(dcm.RescaleIntercept)\n        slope = float(dcm.RescaleSlope)\n    arr = (arr * slope) + intercept\n\n    #window\n    if width is None or level is None:\n        width,level = get_window_from_dicom(dcm)\n    \n    upper, lower = level+width//2, level-width//2\n    arr = np.clip(arr, lower, upper)\n    arr = arr - lower\n    arr = arr / (upper - lower)\n  \n    if scaled:\n        arr = (arr * 256).astype(np.uint8) \n    return arr\n\ndef get_window_from_dicom(dcm, default = (400, 50)):\n    \"\"\"\n    Returns window width and window center values or first example if MultiValue\n    Strips comma from value if present (seen in a different dataset)\n    If no window width/level is provided or available, returns default.\n    \"\"\"\n    width, level = default\n\n    if \"WindowWidth\" in dcm:\n        width = dcm.WindowWidth\n        if isinstance(width, pydicom.multival.MultiValue):\n            width = float(width[0])\n        else:\n            width = float(str(width).replace(',', ''))\n\n    if \"WindowCenter\" in dcm:\n        level = dcm.WindowCenter\n        if isinstance(level, pydicom.multival.MultiValue):\n            level = float(level[0])\n        else:\n            level = float(str(level).replace(',', ''))\n            \n    return width, level","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:32:33.555808Z","iopub.execute_input":"2024-05-17T16:32:33.556238Z","iopub.status.idle":"2024-05-17T16:32:33.568890Z","shell.execute_reply.started":"2024-05-17T16:32:33.556204Z","shell.execute_reply":"2024-05-17T16:32:33.567537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Read Dicom and convert to stack using every other image","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\nstack= np.array([dcmread_to_array(fn) for fn in im_list[::2]])\nlen(stack)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:33:17.226418Z","iopub.execute_input":"2024-05-17T16:33:17.226816Z","iopub.status.idle":"2024-05-17T16:33:17.482707Z","shell.execute_reply.started":"2024-05-17T16:33:17.226784Z","shell.execute_reply":"2024-05-17T16:33:17.481483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Coronal view (ignore pixels at front and back and take every nth image)","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\nignore_pixels = 25\n\n#Change this to get more images\ninterval = 10\n\ncor = stack[:,ignore_pixels:-ignore_pixels:interval,:]\ncor = np.swapaxes(cor,0,1)\ncor.shape","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:33:53.348178Z","iopub.execute_input":"2024-05-17T16:33:53.348672Z","iopub.status.idle":"2024-05-17T16:33:53.358270Z","shell.execute_reply.started":"2024-05-17T16:33:53.348636Z","shell.execute_reply":"2024-05-17T16:33:53.356568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Show one image","metadata":{}},{"cell_type":"code","source":"im = cor[20]\nplt.imshow(im, cmap = 'gray');","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:34:48.073423Z","iopub.execute_input":"2024-05-17T16:34:48.074375Z","iopub.status.idle":"2024-05-17T16:34:48.331681Z","shell.execute_reply.started":"2024-05-17T16:34:48.074332Z","shell.execute_reply":"2024-05-17T16:34:48.330470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Trying another one. Though these images are too \"thin\" and I don't know how to improve that.","metadata":{}},{"cell_type":"code","source":"im1 = cor[13]\nplt.imshow(im1, cmap = 'gray');","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:36:34.546080Z","iopub.execute_input":"2024-05-17T16:36:34.546529Z","iopub.status.idle":"2024-05-17T16:36:34.769933Z","shell.execute_reply.started":"2024-05-17T16:36:34.546496Z","shell.execute_reply":"2024-05-17T16:36:34.768709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#Show images\n#https://stackoverflow.com/questions/41071947/how-to-remove-the-space-between-subplots-in-matplotlib-pyplot\nfrom matplotlib import gridspec\n\ndef show_images(ims, cols = 6):\n    rows = int(np.ceil(len(ims)/cols))\n    img_count = 0\n    \n    fig = plt.figure(figsize=(cols+1, rows+1)) \n\n    gs = gridspec.GridSpec(rows, cols,\n         wspace=0.0, hspace=0.0, \n         top=1.-0.5/(rows+1), bottom=0.5/(rows+1), \n         left=0.5/(cols+1), right=1-0.5/(cols+1)) \n    \n    for i in range(rows):\n        for j in range(cols):\n            if img_count < len(ims):\n                ax= plt.subplot(gs[i,j])\n                ax.imshow(ims[img_count], cmap='gray')\n                ax.set_xticklabels([])\n                ax.set_yticklabels([])\n                \n                img_count+=1\n        \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:37:03.329713Z","iopub.execute_input":"2024-05-17T16:37:03.330174Z","iopub.status.idle":"2024-05-17T16:37:03.339911Z","shell.execute_reply.started":"2024-05-17T16:37:03.330138Z","shell.execute_reply":"2024-05-17T16:37:03.338149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Show initial (unfiltered) coronal images\n\nUnfortunately, it displayed not as I expected :(","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#show initial coronals\nshow_images(cor, cols = 4)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:37:39.351201Z","iopub.execute_input":"2024-05-17T16:37:39.351578Z","iopub.status.idle":"2024-05-17T16:37:41.616377Z","shell.execute_reply.started":"2024-05-17T16:37:39.351548Z","shell.execute_reply":"2024-05-17T16:37:41.614915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Filter by non zero value counts","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#Number of non zero values as a percentage of max\nvals = np.array([np.count_nonzero(cor[i].flatten()) for i in range(len(cor))])\nmost = vals.max()\nvals = np.array([round(val/most * 100) for val in vals])\nvals","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:38:34.936143Z","iopub.execute_input":"2024-05-17T16:38:34.936612Z","iopub.status.idle":"2024-05-17T16:38:34.949861Z","shell.execute_reply.started":"2024-05-17T16:38:34.936577Z","shell.execute_reply":"2024-05-17T16:38:34.947855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n# Get index for values over threshold\nnonzero_threshold = 45\nlen(cor[np.where(vals > nonzero_threshold)])","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:39:09.092007Z","iopub.execute_input":"2024-05-17T16:39:09.092438Z","iopub.status.idle":"2024-05-17T16:39:09.101466Z","shell.execute_reply.started":"2024-05-17T16:39:09.092403Z","shell.execute_reply":"2024-05-17T16:39:09.100138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Only use indices with enough nonzero values\n\nWhy those images are so small/thin??","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#plot better coronal slices\nbetter_cor = cor[np.where(vals > nonzero_threshold)]\nshow_images(better_cor)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:39:26.510321Z","iopub.execute_input":"2024-05-17T16:39:26.510711Z","iopub.status.idle":"2024-05-17T16:39:28.801024Z","shell.execute_reply.started":"2024-05-17T16:39:26.510682Z","shell.execute_reply":"2024-05-17T16:39:28.799948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Dicom to Coronals\n\nPut it all together in a function","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#one series from one exam\ndef dicom_to_coronals(series_path, \n                      interval = 10, \n                      ignore_pixels = 25, \n                      nonzero_threshold = 45):\n    #get filenames\n    im_list = []\n    for dirname, _, filenames in os.walk(series_path):\n        for filename in filenames:\n            im_list.append(os.path.join(dirname, filename))\n\n    #sort\n    im_list.sort(key = lambda o: int(o.split('/')[-1][:-4]))\n    \n    #stack every other\n    stack= np.array([dcmread_to_array(fn) for fn in im_list[::2]])\n\n    #unfiltered coronals\n    cor = stack[:,ignore_pixels:-ignore_pixels:interval,:]\n    cor = np.swapaxes(cor,0,1)\n    \n    #nonzero values\n    vals = np.array([np.count_nonzero(cor[i].flatten()) for i in range(len(cor))])\n    most = vals.max()\n    vals = np.array([round(val/most * 100) for val in vals])\n    \n    #return filtered coronals\n    return cor[np.where(vals > nonzero_threshold)]","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:40:20.040063Z","iopub.execute_input":"2024-05-17T16:40:20.040553Z","iopub.status.idle":"2024-05-17T16:40:20.052792Z","shell.execute_reply.started":"2024-05-17T16:40:20.040518Z","shell.execute_reply":"2024-05-17T16:40:20.050712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#More coronal slices to get more data\n\nImages200+ images\n\nTry it again with more coronal slices to get more data","metadata":{}},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#Change this to get more or less images\ninterval = 2\n\nfiltered_cor = dicom_to_coronals(dn, interval)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:41:03.378039Z","iopub.execute_input":"2024-05-17T16:41:03.378511Z","iopub.status.idle":"2024-05-17T16:41:03.514236Z","shell.execute_reply.started":"2024-05-17T16:41:03.378474Z","shell.execute_reply":"2024-05-17T16:41:03.512647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#By Anouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\n#plot filtered coronal slices\nshow_images(filtered_cor)","metadata":{"execution":{"iopub.status.busy":"2024-05-17T16:43:24.870458Z","iopub.execute_input":"2024-05-17T16:43:24.870961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I have no clue why the snippet above didn't render anything.","metadata":{}},{"cell_type":"markdown","source":"![](https://o.quizlet.com/T1MzRyAROWMkZKJeop9Miw.png)Quizlet","metadata":{}},{"cell_type":"markdown","source":"#Acknowledgements:\n\nMarco Vasquez E https://www.kaggle.com/code/marcovasquez/basic-eda-data-visualization/notebook\n    \nAnouk Stein https://www.kaggle.com/code/anoukstein/dicom-to-coronal\n\nAbdul Basit https://www.kaggle.com/code/abdulbasitniazi/enetb7-explained-98-fine-tuning-eda\n\nRob Mulla https://www.kaggle.com/code/robikscube/sign-language-recognition-eda-twitch-stream","metadata":{}}]}