{"cells":[{"metadata":{},"cell_type":"markdown","source":"This is the 2nd notebook in a series inspired by (and borrowing heavily from) [Jeremy Howard's notebooks](https://www.kaggle.com/c/rsna-intracranial-hemorrhage-detection/discussion/114214) from the 2019 RSNA Intracranial Hemorrhage Challenge.\n\nThe first notebook in the series can be found [here](https://www.kaggle.com/wfwiggins203/extracting-dicom-metadata-labels-with-fast-ai).\n\nHere we'll dig into the DICOM metadata and view some images with `fastai == 2.0.x`. I'll try to inject some of my domain knowledge as a radiologist as we go. _DISCLAIMER: I do NOT subspecialize in thoracic radiology, but rather neuroradiology. Despite that, we all get training in general radiology and detecting PEs is an important skill for any radiologist reading imaging studies of anatomic regions that overlap with the chest (like the neck and spine, in my case)._\n\nAgain, we'll have to start by upgrading the `fastai` library."},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"!pip install fastai --upgrade >/dev/null","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from fastai.medical.imaging import *\nfrom fastai.basics import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path_inp = Path('../input')\npath = path_inp/'rsna-str-pulmonary-embolism-detection'\npath_trn = path/'train'\npath_tst = path/'test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path_df = path_inp/'extracting-dicom-metadata-labels-with-fast-ai'\ndf_lbls = pd.read_feather(path_df/'lbls.fth')\ndf_trn = pd.read_feather(path_df/'df_trn.fth')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Exploring the DICOM metadata\n\nThe `fastai.medical.imaging` library has some nice tools for dealing with DICOM files, built on top of the `pydicom` library. The label for each field in the following table corresponds to a _DICOM tag_ - with the exception of `fname`, which is added by the `fastai` function that created this DataFrame."},{"metadata":{"trusted":true},"cell_type":"code","source":"df_trn.columns","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(42)\ndf_trn.sample(20).T","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Key findings in the DICOM metadata\n\n1. Notice the difference in slice thickness. The vast majority of images are reconstructed with `SliceThickness == 1.25`; however, as you explore the data, you'll notice that some are reconstructed with `SliceThickness == 1.00 || 1.50 || 2.00`.\n2. `Instance Number` is an important attribute for arranging the DICOM images in the appropriate order.\n\nThese findings will have important implications if you're considering reconstructing a volumetric dataset for a 3D CNN architecture."},{"metadata":{},"cell_type":"markdown","source":"# Visualizing DICOM images\n\nThe image data in a DICOM file is the attribute with the `PixelData` tag. The `.show()` method from `fastai` will automatically extract the pixel data and rescale it for display."},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(42)\nfns = L(df_trn.sample(12)['fname'].values.tolist())\ndcms = fns.map(dcmread)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"I got an error when trying to plot some of these images that the `GDCM` package was missing, so we'll install that here."},{"metadata":{"trusted":true},"cell_type":"code","source":"!conda install gdcm -c conda-forge -y >/dev/null","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import gdcm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(len(dcms)):\n    try:\n        dcms[i].show()\n    except:\n        print('GDCM error')\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Looks like installing GDCM didn't exactly fix the error, but at least we can look at most of the images.\n\nA few comments on the above images:\n* `fastai` automatically rescales the pixels for viewing\n* This may not always result in optimal viewing for the task of PE detection as the intravenous contrast (white stuff in the branching pulmonary arterial tree) may obscure underlying filling defects (== PE) if it is too bright\n* However, there are other ways of _windowing_ the pixels, including with the `('WindowCenter', 'WindowWidth', 'RescaleIntercept')` DICOM attributes, which may result in more ideal viewing\n* This is not the ideal viewing size for this task; however, it appears that the 10th image in this series has filling defects == PEs in the right and left lower lobes\n\nLet's take a look at the labels for these images to see if image # 10 is labeled as positive for PE."},{"metadata":{"trusted":true},"cell_type":"code","source":"sops = dcms.map(lambda x: x['SOPInstanceUID'].value)\ndf_lbls.set_index('SOPInstanceUID').loc[sops]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Suspicion confirmed! That's all for now... I'll try to come back later and add more to this series."}],"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":4,"nbformat_minor":4}