{"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":"Published on July 26, 2023. By Marília Prata, mpwolke.","metadata":{"_kg_hide-input":false}},{"cell_type":"markdown","source":"![](https://osmose-it.s3.amazonaws.com/wVl7WRLcQ8201DX8Dt6ZXgJoQ1iZSKGB/_.jpg)\nhttps://www.osmosis.org/learn/Abdominal_trauma:_Clinical_practice","metadata":{}},{"cell_type":"markdown","source":"\"Blunt abdominal trauma is a leading cause of morbidity and mortality among all age groups. Identification of serious intra-abdominal pathology is often challenging; many injuries may not manifest during the initial assessment and treatment period.\"\n\n\"Computed tomography is the standard for detecting solid organ injuries. CT scans provide excellent imaging of the pancreas, duodenum, and genitourinary system.\"\n\n\"CT scanning often provides the most detailed images of traumatic pathology and may assist in determination of operative intervention. Unlike DPL or FAST, CT can determine the source of hemorrhage.\"\n\nhttps://emedicine.medscape.com/article/1980980-overview?form=fpf","metadata":{}},{"cell_type":"markdown","source":"#Competition Citation\n\n@misc{rsna-2023-abdominal-trauma-detection,\n\n    author = {Adam Flanders, Chris Carr, Errol Colak, HCL-Jevster, Hui Ming Lin, JeffRudie, John Mongan,\n    Luciano Prevedello, Maggie, Martin Görner, Maryam Vazirabad, Michelle Riopel, Robyn Ball},\n    \n    title = {RSNA 2023 Abdominal Trauma Detection},\n    \n    publisher = {Kaggle},\n    \n    year = {2023},\n    \n    url = {https://kaggle.com/competitions/rsna-2023-abdominal-trauma-detection}\n}","metadata":{}},{"cell_type":"code","source":"%%capture\n\n!pip install -U dicomsdl -q ","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:39:59.355957Z","iopub.execute_input":"2023-07-26T22:39:59.356296Z","iopub.status.idle":"2023-07-26T22:40:08.462043Z","shell.execute_reply.started":"2023-07-26T22:39:59.356272Z","shell.execute_reply":"2023-07-26T22:40:08.460942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import dicomsdl as dicoml\nimport cv2\n\nimport glob\nimport time\nimport numpy as np\nimport random\n\nfrom matplotlib import pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:40:25.442211Z","iopub.execute_input":"2023-07-26T22:40:25.442523Z","iopub.status.idle":"2023-07-26T22:40:25.447485Z","shell.execute_reply.started":"2023-07-26T22:40:25.442498Z","shell.execute_reply":"2023-07-26T22:40:25.446386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\nFILE_SIZE = 512\n\n# take images patients directory\ntrain_group = glob.glob(\"/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/**/*/\")\nprint(f'Patients for processing: {len(train_group)}')","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:43:46.205708Z","iopub.execute_input":"2023-07-26T22:43:46.206034Z","iopub.status.idle":"2023-07-26T22:43:50.844838Z","shell.execute_reply.started":"2023-07-26T22:43:46.206012Z","shell.execute_reply":"2023-07-26T22:43:50.844214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Ray\n\n\"Ray is an open-source unified framework for scaling AI and Python applications. It provides the compute layer for parallel processing so that you don’t need to be a distributed systems expert.\"\n\nhttps://docs.ray.io/en/latest/index.html#\n\n\"Ray is a unified framework for scaling AI and Python applications. Ray consists of a core distributed runtime and a toolkit of libraries (Ray AIR) for simplifying ML compute.\"\nhttps://github.com/ray-project/ray","metadata":{}},{"cell_type":"markdown","source":"![](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSOcwPqfGuXSjmFuCl0idrSggDTE5zLe_nS9PRMAjXu92QquFdbiYWzUn2e8YcG0QthBIk&usqp=CAU)twitter","metadata":{}},{"cell_type":"code","source":"import ray\nray.init(log_to_driver=False)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:44:07.025954Z","iopub.execute_input":"2023-07-26T22:44:07.02629Z","iopub.status.idle":"2023-07-26T22:44:12.598744Z","shell.execute_reply.started":"2023-07-26T22:44:07.026268Z","shell.execute_reply":"2023-07-26T22:44:12.597737Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\ndef process_faster(f, size=512, save_folder=None, dicom_process = True, extension=\"png\", group_id = 0):\n    \n    patient = f.split('/')[-2]\n    image_name = f.split('/')[-1][:-4]\n\n    image = np.array(dicoml.open(f).toPilImage())\n    img = cv2.resize(image, (size, size))\n\n    file_name = f'{save_folder}' + f\"{patient}_{image_name}.{extension}\"\n    cv2.imwrite(file_name, img)\n\n# sample function - draw circle in center of the image\ndef draw_circle(img_files):\n    for f_img in img_files:\n        img = cv2.imread(f_img)\n        cv2.circle(img, (int(FILE_SIZE // 2),int(FILE_SIZE // 2)), 20, (255,0,0), 3)\n        cv2.imwrite(f_img, img)\n\n\n@ray.remote\nclass MessageActor(object):\n    def __init__(self):\n        self.messages = []\n    \n    def add_message(self, message):\n        self.messages.append(message)\n    \n    def get_and_clear_messages(self):\n        messages = self.messages\n        self.messages = []\n        return messages\n\n@ray.remote\ndef group_processor(group_id):\n    # This function process all dicom files for particular patient ID\n    files = glob.glob(f'/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/*/{group_id}/*.dcm')\n    \n    # process all files in directory\n    for f in files:\n        res = process_faster(f, size = FILE_SIZE, save_folder = '', dicom_process = False)\n    \n    # when finished task send message to queue - \"task finished all files for patient ID were processed\" \n    message_actor.add_message.remote(f\"p-{group_id}\")\n    \n@ray.remote\ndef process_group(group_id):\n    # task X on all files from group e.g. make prediction\n    # this is sample so I decided to:\n    # a. check number of files in directory\n    # b. draw a small circle on image \n    \n    files = glob.glob(f'{group_id}/*/_*.png')\n    count = len(files)\n    draw_circle(files)\n    # send message to queue - task finished\n    message_actor.add_message.remote(f\"d-{group_id},{count}\")\n    \nmessage_actor = MessageActor.remote()","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:46:15.122357Z","iopub.execute_input":"2023-07-26T22:46:15.12355Z","iopub.status.idle":"2023-07-26T22:46:15.148115Z","shell.execute_reply.started":"2023-07-26T22:46:15.123524Z","shell.execute_reply":"2023-07-26T22:46:15.147107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\nLIMIT = 25 # we process only 25 patients\nall_files = 0\nstart_time = time.time()\n\n# As a sample process 20 clients\nfor g in train_group[:LIMIT]:\n    group_id = g.split('/')[-2]\n    # run it parallel\n    group_processor.remote(group_id)\n\n# Now we will listen all messages \nwhile True:\n    # waiting for task finished\n    # we have 2 task defined\n    # task1 - processing dicom files for particular patient\n    # task2 - sample function \n    \n    new_messages = ray.get(message_actor.get_and_clear_messages.remote())\n    \n    # check messages from queue\n    for message in new_messages:\n        # tokenize message\n        message_tokens = message.split('-')[-1].split(',')\n        \n        # message from task1?\n        if message[0]=='p':\n            print(f'Finished task1 for patient {message_tokens[0]}')\n            \n            # call second step of procesing - we know that all files for pateint X are processed \n            process_group.remote(message.split('-')[-1])\n            LIMIT -= len(new_messages)\n        \n        #message from task2?\n        elif message[0]=='d':\n            message_tokens = message.split('-')[-1].split(',')\n            all_files += int(message_tokens[-1])\n            print(f\"Finished task2 for patient {message_tokens[0]} number of files {message_tokens[-1]}\")\n    \n    # we run 10 task - so we check if all are processed\n    if not LIMIT:\n        break\n        \nprint(f\"End of processing {all_files} files - time: {time.time()-start_time}\")\n\nray.shutdown()","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:46:52.297252Z","iopub.execute_input":"2023-07-26T22:46:52.297593Z","iopub.status.idle":"2023-07-26T22:47:48.159374Z","shell.execute_reply.started":"2023-07-26T22:46:52.297569Z","shell.execute_reply":"2023-07-26T22:47:48.158346Z"},"_kg_hide-output":true,"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\nn = 4\nout_files = glob.glob(f'./*.png')\n\nfig, axs = plt.subplots(1, n, figsize=(25, 25))\nfor idx, im_file in enumerate(random.sample(out_files, n)):\n    im = cv2.imread(im_file)\n    axs[idx].imshow(im)\nplt.show() ","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:48:36.225463Z","iopub.execute_input":"2023-07-26T22:48:36.225805Z","iopub.status.idle":"2023-07-26T22:48:37.100425Z","shell.execute_reply.started":"2023-07-26T22:48:36.225779Z","shell.execute_reply":"2023-07-26T22:48:37.098229Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Fast dicom by Remek Kinas\n\n@kaggleqrdl found it and discussed here: https://www.kaggle.com/competitions/rsna-breast-cancer-detection/discussion/369684#2057282\n\nhttps://www.kaggle.com/code/remekkinas/fast-dicom-processing-1-6-2x-faster","metadata":{}},{"cell_type":"code","source":"%%capture\n\n!pip install -U dicomsdl -q \n\ntry:\n    import pylibjpeg\nexcept:\n   !pip install /kaggle/input/rsna-2022-whl/{pylibjpeg-1.4.0-py3-none-any.whl,python_gdcm-3.0.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl}","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:49:07.240964Z","iopub.execute_input":"2023-07-26T22:49:07.242006Z","iopub.status.idle":"2023-07-26T22:49:17.835215Z","shell.execute_reply.started":"2023-07-26T22:49:07.241977Z","shell.execute_reply":"2023-07-26T22:49:17.833373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\nimport dicomsdl as dicoml\nimport cv2\nimport pydicom\n\nfrom joblib import Parallel, delayed\nimport glob\nimport time\nimport numpy as np\nimport os\nfrom matplotlib import pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:49:28.447144Z","iopub.execute_input":"2023-07-26T22:49:28.447515Z","iopub.status.idle":"2023-07-26T22:49:28.566146Z","shell.execute_reply.started":"2023-07-26T22:49:28.447489Z","shell.execute_reply":"2023-07-26T22:49:28.565192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://www.kaggle.com/code/remekkinas/fast-dicom-processing-1-6-2x-faster\n\nimage_dir_pydicom = '/kaggle/working/png_file_py/'\nimage_dir_dicomsdl = '/kaggle/working/png_file_dic/'\n\nos.makedirs(image_dir_pydicom, exist_ok=True)\nos.makedirs(image_dir_dicomsdl, exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:49:48.532293Z","iopub.execute_input":"2023-07-26T22:49:48.532624Z","iopub.status.idle":"2023-07-26T22:49:48.539394Z","shell.execute_reply.started":"2023-07-26T22:49:48.532601Z","shell.execute_reply":"2023-07-26T22:49:48.538052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images = glob.glob(\"/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/**/*/*.dcm\")\nlen(train_images)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:51:54.574332Z","iopub.execute_input":"2023-07-26T22:51:54.574694Z","iopub.status.idle":"2023-07-26T22:53:02.882039Z","shell.execute_reply.started":"2023-07-26T22:51:54.57467Z","shell.execute_reply":"2023-07-26T22:53:02.880902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/fast-dicom-processing-1-6-2x-faster\n\ndef process(f, size=512, save_folder=None, dicom_process = True, extension=\"png\"):\n    \n    patient = f.split('/')[-2]\n    image_name = f.split('/')[-1][:-4]\n    if dicom_process:\n        dicom = pydicom.dcmread(f)\n        img = dicom.pixel_array\n\n        img = (img - img.min()) / (img.max() - img.min())\n\n        if dicom.PhotometricInterpretation == \"MONOCHROME1\":  # You may want to uncomment this\n            img = 1 - img\n            \n        image = (img * 255).astype(np.uint8)\n    else:\n        image = np.array(dicoml.open(f).toPilImage())\n\n    img = cv2.resize(image, (size, size))\n\n    file_name = f'{save_folder}' + f\"{patient}_{image_name}.{extension}\"\n\n    cv2.imwrite(file_name, img)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:53:27.971249Z","iopub.execute_input":"2023-07-26T22:53:27.971602Z","iopub.status.idle":"2023-07-26T22:53:28.011652Z","shell.execute_reply.started":"2023-07-26T22:53:27.971577Z","shell.execute_reply":"2023-07-26T22:53:28.010581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/fast-dicom-processing-1-6-2x-faster\n\nstart_time = time.time()\n        \nParallel(n_jobs=4)(\n    delayed(process)(f, size = 512, save_folder = image_dir_pydicom, dicom_process = True)\n    for f in train_images[:500]\n)\n\nprint(time.time() - start_time)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:53:33.494859Z","iopub.execute_input":"2023-07-26T22:53:33.495204Z","iopub.status.idle":"2023-07-26T22:53:38.193643Z","shell.execute_reply.started":"2023-07-26T22:53:33.495179Z","shell.execute_reply":"2023-07-26T22:53:38.192499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/fast-dicom-processing-1-6-2x-faster\n\nout_files = glob.glob(f'{image_dir_pydicom}*.png')\nfor idx, i in enumerate(out_files[:4]):\n    im = cv2.imread(i)\n    print(f'file {i} size in bytes: {os.path.getsize(i)}, shape: {im.shape}')\n    plt.imshow(im)\n    plt.show(); ","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:54:41.923849Z","iopub.execute_input":"2023-07-26T22:54:41.924219Z","iopub.status.idle":"2023-07-26T22:54:43.104215Z","shell.execute_reply.started":"2023-07-26T22:54:41.924194Z","shell.execute_reply":"2023-07-26T22:54:43.102811Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#dicomsdl - speed test\n","metadata":{}},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\nstart_time = time.time()\n        \nParallel(n_jobs=4)(\n    delayed(process)(f, size = 512, save_folder = image_dir_dicomsdl, dicom_process = False)\n    for f in train_images[:500]\n)\n\nprint(time.time() - start_time)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:55:07.099573Z","iopub.execute_input":"2023-07-26T22:55:07.099902Z","iopub.status.idle":"2023-07-26T22:55:08.601247Z","shell.execute_reply.started":"2023-07-26T22:55:07.099878Z","shell.execute_reply":"2023-07-26T22:55:08.600088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Remek Kinas https://www.kaggle.com/code/remekkinas/fast-dicom-processing-1-6-2x-faster\n\nout_files = glob.glob(f'{image_dir_dicomsdl}*.png')\nfor i in out_files[:4]:\n    im = cv2.imread(i)\n    print(f'file {i} size in bytes: {os.path.getsize(i)}, shape: {im.shape}')\n    plt.imshow(im)\n    plt.show() ","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:55:59.826461Z","iopub.execute_input":"2023-07-26T22:55:59.826773Z","iopub.status.idle":"2023-07-26T22:56:00.597206Z","shell.execute_reply.started":"2023-07-26T22:55:59.82675Z","shell.execute_reply":"2023-07-26T22:56:00.59573Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#We can see there is improvement in speed but further investigation in image quality is needed.\n\nIn fact, I can't see anything. I'm just copying Kinas code and hurry to change mam's dipper.","metadata":{}},{"cell_type":"markdown","source":"#Another DICOM processing notebook ","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pydicom\nimport matplotlib.pyplot as plt\nimport cv2\nfrom pydicom.pixel_data_handlers import apply_voi_lut","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:56:23.750709Z","iopub.execute_input":"2023-07-26T22:56:23.751067Z","iopub.status.idle":"2023-07-26T22:56:23.757416Z","shell.execute_reply.started":"2023-07-26T22:56:23.751042Z","shell.execute_reply":"2023-07-26T22:56:23.755824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#David Roberts code!","metadata":{}},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-pad-to-square\n\n# This function is for extracting pixels from DICOM files.\n#\ndef get_pixels(dcm_file):\n    im = pydicom.dcmread(dcm_file)\n    \n    data = im.pixel_array\n    \n    data = apply_voi_lut(data, im)\n    \n    if im.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    else:\n        data = data - np.min(data)\n        \n    if np.max(data) != 0:\n        data = data / np.max(data)\n    data=(data * 255).astype(np.uint8)\n    \n    return data","metadata":{"execution":{"iopub.status.busy":"2023-07-26T22:59:32.440855Z","iopub.execute_input":"2023-07-26T22:59:32.441245Z","iopub.status.idle":"2023-07-26T22:59:32.448864Z","shell.execute_reply.started":"2023-07-26T22:59:32.441222Z","shell.execute_reply":"2023-07-26T22:59:32.44759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Grab a random image\n\nYou'll need to install GDCM and pylibjpeg to open some of JPG compressed Abdominal images in this dataset.","metadata":{}},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-pad-to-square\n\n# Open an image and get pixels \npixels = get_pixels(\"/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10005/18667/100.dcm\")\n\n# Pad the original pixels to make them square\npixels_padded = pad_pixels(pixels)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:15:25.53378Z","iopub.execute_input":"2023-07-26T23:15:25.534185Z","iopub.status.idle":"2023-07-26T23:15:25.554787Z","shell.execute_reply.started":"2023-07-26T23:15:25.534142Z","shell.execute_reply":"2023-07-26T23:15:25.553307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"I wasn't able to pad the pixel. Therefore, I'll save that above for the next time.","metadata":{}},{"cell_type":"markdown","source":"#Windowing","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pydicom\nimport matplotlib.pyplot as plt\nimport cv2\nfrom pydicom.pixel_data_handlers import apply_windowing","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:10:21.874953Z","iopub.execute_input":"2023-07-26T23:10:21.875362Z","iopub.status.idle":"2023-07-26T23:10:21.881564Z","shell.execute_reply.started":"2023-07-26T23:10:21.875335Z","shell.execute_reply":"2023-07-26T23:10:21.880135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-apply-windowing\n\n# This function uses pydicom's apply_windowing() function to apply the default window width and level specified in the DICOM tags\n\ndef get_pixels_with_windowing(dcm_file):\n    im = pydicom.dcmread(dcm_file)\n    \n    data = im.pixel_array\n    \n    # This line is the only difference in the two functions\n    data = apply_windowing(data, im)\n    \n    if im.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    else:\n        data = data - np.min(data)\n        \n    if np.max(data) != 0:\n        data = data / np.max(data)\n    data=(data * 255).astype(np.uint8)\n\n    return data","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:11:33.755739Z","iopub.execute_input":"2023-07-26T23:11:33.756144Z","iopub.status.idle":"2023-07-26T23:11:33.762713Z","shell.execute_reply.started":"2023-07-26T23:11:33.756117Z","shell.execute_reply":"2023-07-26T23:11:33.761444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-apply-windowing\n\n# Open an image and get the pixels twice .. once without windowing and once with it.\n#\nfile = \"/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10005/18667/100.dcm\"\npixels = get_pixels(file)\npixels_with_windowing = get_pixels_with_windowing(file)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:13:09.92272Z","iopub.execute_input":"2023-07-26T23:13:09.923085Z","iopub.status.idle":"2023-07-26T23:13:09.960625Z","shell.execute_reply.started":"2023-07-26T23:13:09.92306Z","shell.execute_reply":"2023-07-26T23:13:09.959837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-apply-windowing\n\n# Plot the images\nfig, axes = plt.subplots(nrows=1, ncols=2,sharex=False, sharey=True, figsize=(14, 10))\nax = axes.ravel()\nax[0].set_title(f'Standard normalization')\nax[0].imshow(pixels, cmap='gray');\nax[1].set_title(f'With windowing')\nax[1].imshow(pixels_with_windowing, cmap='gray');","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:13:28.796718Z","iopub.execute_input":"2023-07-26T23:13:28.797063Z","iopub.status.idle":"2023-07-26T23:13:29.284353Z","shell.execute_reply.started":"2023-07-26T23:13:28.79704Z","shell.execute_reply":"2023-07-26T23:13:29.283478Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Notice the image on the right looks less \"washed out\" and the contrast between soft and dense tissue is greater","metadata":{}},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-apply-windowing\n\n# Open another image and take a look\n#\nfile = \"/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10132/4816/174.dcm\"\npixels = get_pixels(file)\npixels_with_windowing = get_pixels_with_windowing(file)","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:21:31.40138Z","iopub.execute_input":"2023-07-26T23:21:31.401743Z","iopub.status.idle":"2023-07-26T23:21:31.445533Z","shell.execute_reply.started":"2023-07-26T23:21:31.401717Z","shell.execute_reply":"2023-07-26T23:21:31.444222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#David Roberts https://www.kaggle.com/code/davidbroberts/mammography-apply-windowing\n\n# Plot the images\nfig, axes = plt.subplots(nrows=1, ncols=2,sharex=False, sharey=True, figsize=(14, 10))\nax = axes.ravel()\nax[0].set_title(f'Standard normalization')\nax[0].imshow(pixels, cmap='gray');\nax[1].set_title(f'With windowing')\nax[1].imshow(pixels_with_windowing, cmap='gray');","metadata":{"execution":{"iopub.status.busy":"2023-07-26T23:21:36.250229Z","iopub.execute_input":"2023-07-26T23:21:36.250601Z","iopub.status.idle":"2023-07-26T23:21:36.755234Z","shell.execute_reply.started":"2023-07-26T23:21:36.250571Z","shell.execute_reply":"2023-07-26T23:21:36.754509Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#Windowing conclusion\n\nApplying windowing to DICOM images provides much better contrast and width of images.\n\nThis technique should be applied to JPG/PNG exports.\n\nIf the pydicom function apply_voi_lut() is used, it will also apply the default WW/WL values if a LUT does not exist .. which they routinely do not exist in mammography.\n\nApplying windowing allows for greater range when manually adjusting brightness/contrast later.\n\nhttps://www.kaggle.com/code/davidbroberts/mammography-apply-windowing","metadata":{}},{"cell_type":"markdown","source":"#Acknowledgements:\n\nRemek Kinas https://www.kaggle.com/code/remekkinas/ray-parallel-processing-dicom-files-and/notebook\n\nDavid Roberts https://www.kaggle.com/code/davidbroberts/mammography-apply-windowing","metadata":{}}]}