{"cells":[{"metadata":{},"cell_type":"markdown","source":"<h1>Pre-process I used in the competition</h1>\n\nI used the information contained in the images by performing lung segmentation first.\n\nI intended to use this library : \nhttps://github.com/JoHof/lungmask\n\nThe library allows to detect masks for left and right lung. \nNevertheless I could not use it as it seems that Skimage could not be imported in this competition.\nTherefore I used another segmentation tool I found in [this notebook](https://www.kaggle.com/super13579/ed-simple-method-of-lung-segmentation) posted on Kaggle by @funkyboy.\n\nAfter obtaining a mask, and as I had no other way to detect the right lung from the left one, I just used a rough method, and just divided the mask image into two, vertically, and considered that the left lung is in the left half of the mask while the right lung is in the right half of the mask. I then calculated the area of the left and right lung and then the volume, and used this information as features.\n\nI did not use a CNN because I believed the processing time will  be longer than the one allowed for this competition.\n\n\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"!conda install -c conda-forge gdcm -y","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport sys\nimport math\nimport random\nfrom tqdm import tqdm\nimport itertools\n#import fill_voids\nimport logging\nimport datetime\nfrom datetime import datetime, timedelta\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib\n\nfrom sklearn.metrics import mean_absolute_error\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom sklearn.decomposition import PCA\n\nfrom PIL import Image\nimport pydicom as dcm\nfrom pydicom.pixel_data_handlers.util import apply_modality_lut\nfrom pydicom.pixel_data_handlers.gdcm_handler import *\n\nimport glob\nfrom skimage import morphology, io, color, exposure, img_as_float, transform\nimport skimage.measure\n\nfrom keras.models import load_model\nfrom keras.preprocessing.image import ImageDataGenerator\n\n#from lung-segmentation.lungmask import mask, utils\nfrom skimage.segmentation import clear_border\nfrom skimage.measure import label, regionprops\nfrom skimage.morphology import disk, dilation, binary_erosion, binary_closing\nfrom skimage.filters import roberts, sobel\nimport cv2\nfrom scipy import ndimage as ndi\n\nimport torch\nfrom torch import nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"ROOT = '/kaggle/input/rsna-str-pulmonary-embolism-detection'\nPATH_TRAIN_IMAGES = ROOT + '/train/'\nPATH_TEST_IMAGES = ROOT + '/test/'\n\ndf_train = pd.read_csv('/kaggle/input/rsna-str-pulmonary-embolism-detection/train.csv')\ndf_test = pd.read_csv('/kaggle/input/rsna-str-pulmonary-embolism-detection/test.csv')\nsub = pd.read_csv('/kaggle/input/rsna-str-pulmonary-embolism-detection/sample_submission.csv')\n\n# New features to add : \ndf_train = df_train.assign(area=0, area_real=0, area_mean_per_study=0, area_min_per_study=0, area_max_per_study=0, pixel_spacing_height=0, pixel_spacing_width=0, slice_thickness=0)\ndf_test = df_test.assign(area=0, area_real=0, area_mean_per_study=0, area_min_per_study=0, area_max_per_study=0, pixel_spacing_height=0, pixel_spacing_width=0, slice_thickness=0)\nsub = sub.assign(area=0, area_real=0, area_mean_per_study=0, area_min_per_study=0, area_max_per_study=0, pixel_spacing_height=0, pixel_spacing_width=0, slice_thickness=0)\n      ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Classes I used:"},{"metadata":{"trusted":true},"cell_type":"code","source":"class DataImage():\n    def __init__(self):\n        self.substudy=''\n        self.study=''\n        self.file_name=''\n        self.pixel_spacing_height=0\n        self.pixel_spacing_width=0\n        self.slice_thickness=0\n        self.np_lung=np.array((512,512))\n        self.np_mask=np.array((512,512))\n        self.lung_area=0\n        self.lung_area_real=0\n        self.lung_area_1=0\n        self.lung_area_2=0\n        self.real_lung_area_1=0\n        self.real_lung_area_2=0\n        \n    def to_string(self):\n        print(\"Class DataImage:\")\n        print(\"File name: \", self.file_name) \n        print(\"Pixel spacing height: \", self.pixel_spacing_height)\n        print(\"Pixel spacing width: \", self.pixel_spacing_width)\n        print(\"Slicethickness: \", self.slice_thickness)\n        \n        \nclass DataPatient():\n    def __init__(self, s, sbs, w):\n        self.study=s\n        self.substudy=sbs\n        self.where=w\n        self.data_images = []\n        \n    def to_string(self):\n        print(\"Class DataPatient:\")\n        print(\"Study: \", self.study)\n        print(\"Subtudy: \", self.substudy)\n        print(\"Where: \", self.where)\n        print(\"Images: \", self.data_images)\n        \ndef preprocess(df):\n    df1 = df.groupby(by=['StudyInstanceUID']).count()\n    df['nb_images_per_study'] = df.apply(lambda row: df1.loc[row['StudyInstanceUID'], 'SeriesInstanceUID'], axis=1)\n    \n    return df\n\ndef score_series(y_test_col, y_val_predict, col):\n    score = -weights[col] * log_loss(y_test_col, y_val_predict)\n    return score\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Image segmentation functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_segmented_lungs(im2, plot=False):\n    im = im2.copy()\n    # Step 1: Convert into a binary image.\n    binary = im < -400\n    \n    if plot:\n        plt.imshow(binary)\n        plt.show()\n        \n    # Step 2: Remove the blobs connected to the border of the image.\n    cleared = clear_border(binary)\n    \n    if plot:\n        plt.imshow(cleared)\n        plt.show()    \n        \n    # Step 3: Label the image.\n    label_image = label(cleared)\n    \n    if plot:\n        plt.imshow(label_image)\n        plt.show()    \n        \n    # Step 4: Keep the labels with 2 largest areas.\n    areas = [r.area for r in regionprops(label_image)]\n    areas.sort()\n    if len(areas) > 0:\n        for region in regionprops(label_image):\n            if region.area < areas[0]:\n                for coordinates in region.coords:\n                       label_image[coordinates[0], coordinates[1]] = 0\n    binary = label_image > 0\n    \n    if plot:\n        plt.imshow(binary)\n        plt.show()  \n        \n    # Step 5: Erosion operation with a disk of radius 2. This operation is seperate the lung nodules attached to the blood vessels.\n    selem = disk(2)\n    binary = binary_erosion(binary, selem)\n    \n    if plot:\n        plt.imshow(binary)\n        plt.show()  \n        \n    # Step 6: Closure operation with a disk of radius 10. This operation is to keep nodules attached to the lung wall.\n    selem = disk(10) # CHANGE BACK TO 10\n    binary = binary_closing(binary, selem)\n    \n    if plot:\n        plt.imshow(binary)\n        plt.show() \n        \n    # Step 7: Fill in the small holes inside the binary mask of lungs.\n    edges = roberts(binary)\n    \n    if plot:\n        plt.imshow(edges)\n        plt.show() \n        \n    binary = ndi.binary_fill_holes(edges)\n    \n    if plot:\n        plt.imshow(binary)\n        plt.show() \n        \n    # Step 8: Superimpose the binary mask on the input image.\n    selem = disk(4)\n    binary = dilation(binary, selem)\n    get_high_vals = binary == 0\n    im[get_high_vals] = -2000\n    \n    if plot:\n        plt.imshow(im)\n        plt.show()\n        \n    return im, binary\n\ndef get_mask_for_one_image(image_path):\n    #dicom = data_path+studyID+\"/\"+SeriesID+\"/\"+SOPID+\".dcm\"\n    img = dcm.dcmread(image_path)\n    d = DataImage()\n    \n    d.pixel_spacing_height = float(img.PixelSpacing[0])\n    d.pixel_spacing_width = float(img.PixelSpacing[1])\n    d.slice_thickness = float(img.SliceThickness)\n    \n    img_data = img.pixel_array # Read the pixel value\n    hu = apply_modality_lut(img_data, img) # Transform to HU value\n    lung_seg, _ = get_segmented_lungs(hu)\n    minval = np.amin(lung_seg)\n    s1 = lung_seg>minval\n    area = s1.sum()\n    \n    d.lung_area=area\n    d.lung_area_real= area * d.pixel_spacing_width * d.pixel_spacing_height\n    d.np_lung=hu\n    d.np_mask=lung_seg\n    \n    return d\n\n\ndef get_mask_for_one_series(dir_study, p):\n    count=0\n    for i, filename in enumerate(os.listdir(dir_study)):\n        count = count+1\n        (lung_seg, hu, area) = get_mask_for_one_image(dir_study + filename)\n        \n        d = DataImage()\n        d.study = study\n        d.substudy = substudy\n        d.file_name=filename\n        d.np_lung=hu\n        d.np_mask=lung_seg\n        d.lung_area = area\n        p.data_images.append(d)\n    return p    \n        ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This is the segmentation for the training set. The one for the test set is similar."},{"metadata":{"trusted":true},"cell_type":"code","source":"c=0\nfor dirname, studies, filenames in os.walk(ROOT+'/train/'):\n    studies.sort(reverse=False)\n    for study in studies:\n        c += 1   \n        print(study+\" \"+str(c))\n        df_train_study = df_train.loc[df_train['StudyInstanceUID']==study]\n        study = str(study)\n        for dirname2, substudies, filenames in os.walk(ROOT+'/train/'+study+'/'):\n            for substudy in substudies:\n                dir_study = PATH_TRAIN_IMAGES+study+'/'+substudy+'/'\n                p = DataPatient(study, substudy, 'TRAIN')\n                #(lung_seg, hu, area) = get_mask_for_one_series(dir_study, p)\n                for i, filename in enumerate(os.listdir(dir_study)):\n                    d = get_mask_for_one_image(dir_study + str(filename))\n                    filename = str(filename)\n                    im_name = \"train_\"+study+\"_\"+substudy+\"_\"+filename[:-4]\n                    #matplotlib.image.imsave(im_name+'.jpg', d.np_mask)\n                    df_train_study.loc[(df_train_study['SeriesInstanceUID']==substudy) & (df_train_study['SOPInstanceUID']==filename[:-4]), 'area'] = d.lung_area\n                    df_train_study.loc[(df_train_study['SeriesInstanceUID']==substudy) & (df_train_study['SOPInstanceUID']==filename[:-4]), 'area_real'] = d.lung_area_real\n                    \n                    df_train_study.loc[(df_train_study['SeriesInstanceUID']==substudy) & (df_train_study['SOPInstanceUID']==filename[:-4]), 'pixel_spacing_height'] = d.pixel_spacing_height\n                    df_train_study.loc[(df_train_study['SeriesInstanceUID']==substudy) & (df_train_study['SOPInstanceUID']==filename[:-4]), 'pixel_spacing_width'] = d.pixel_spacing_width\n                    df_train_study.loc[(df_train_study['SeriesInstanceUID']==substudy) & (df_train_study['SOPInstanceUID']==filename[:-4]), 'slice_thickness'] = d.slice_thickness\n             \n        df_train_study_nonzero = df_train_study.loc[df_train_study['area']>0]\n        \n        val_min = df_train_study_nonzero['area_real'].min()\n        val_max = df_train_study_nonzero['area_real'].max()\n        val_mean = df_train_study_nonzero['area_real'].mean()\n        \n        df_train_study.loc[:,'area_mean_per_study'] = val_mean\n        df_train_study.loc[:,'area_min_per_study'] = val_min\n        df_train_study.loc[:,'area_max_per_study'] = val_max\n        \n        df_train_study.loc[:,'nb_images_per_study'] = df_train_study.shape[0]\n        \n        df_train_study.to_csv('df_train_'+str(study)+'.csv')\n        \n    break\n    print(\"End Train\") \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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}