{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Introduction"},{"metadata":{},"cell_type":"markdown","source":"* The goal of this notebook is to investigate a metric for describing the state of the lung's fibrosis allowing for comparison among patients of varying characterisitcs. \n* FVC alone should not be a great indicator for the state of the lung's fibrosis as it most probably should depend linearly on the lungs's volume regarded as an empty vessel.\n* The tabular data offers the Percent column which is described as the fraction of an FVC value divided by a FVC value typical for a person with similar characterisitcs. \n* However, I thought the most straightforward way for describing the state of the lung's fibrosis should be the FVC divided by the lung's volume regarded as an empty vessel."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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\n#for 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 5GB 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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#These installations are necessary in order to open all scans\n!conda install -c conda-forge gdcm -y\n!conda install -c conda-forge pillow -y\n!conda install -c conda-forge pydicom -y\n!conda install -c conda-forge tslearn -y","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport matplotlib.pyplot as plt\n\nimport time\nimport math\n\nimport cv2\nimport random\nimport pydicom\nimport warnings\n\nfrom glob import glob\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ROOT = '../input/osic-pulmonary-fibrosis-progression'\ntrain_df = pd.read_csv(f'{ROOT}/train.csv')\ntrain_df.drop_duplicates(subset=['Patient','Weeks'], keep = False, inplace = True)\ngroupedbypatient = train_df.groupby('Patient')\npatientimages = groupedbypatient.Patient.first().to_numpy()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Segmentation"},{"metadata":{},"cell_type":"markdown","source":"Taken from @Xie29's great notebook(https://www.kaggle.com/xiejialun/lung-ct-scan-segmentation-model)"},{"metadata":{"trusted":true},"cell_type":"code","source":"INPUT_FOLDER = '/kaggle/input/osic-pulmonary-fibrosis-progression/train/'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def load_scan(path):\n    \"\"\"\n    Loads scans from a folder and into a list.\n    \n    Parameters: path (Folder path)\n    \n    Returns: slices (List of slices)\n    \"\"\"\n    \n    slices = [pydicom.read_file(path + '/' + s) for s in os.listdir(path)]\n    slices.sort(key = lambda x: int(x.InstanceNumber))   \n   \n        \n    return slices","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_segmentation_model():\n    \n    class FixedDropout(tf.keras.layers.Dropout):\n        def _get_noise_shape(self, inputs):\n            if self.noise_shape is None:\n                return self.noise_shape\n\n            symbolic_shape = tf.keras.backend.shape(inputs)\n            noise_shape = [symbolic_shape[axis] if shape is None else shape\n                           for axis, shape in enumerate(self.noise_shape)]\n            return tuple(noise_shape)\n\n    def DiceCoef(y_trues, y_preds, smooth=1e-5, axis=None):\n        intersection = tf.reduce_sum(y_trues * y_preds, axis=axis)\n        union = tf.reduce_sum(y_trues, axis=axis) + tf.reduce_sum(y_preds, axis=axis)\n        return tf.reduce_mean((2*intersection+smooth) / (union + smooth))\n\n    def DiceLoss(y_trues, y_preds):\n        return 1.0 - DiceCoef(y_trues, y_preds)\n\n    get_custom_objects().update({'swish': tf.keras.layers.Activation(tf.nn.swish)})\n    get_custom_objects().update({'FixedDropout':FixedDropout})\n    get_custom_objects().update({'DiceCoef' : DiceCoef})\n    get_custom_objects().update({'DiceLoss' : DiceLoss})\n    \n    print('Load segmentation model...')\n    model = tf.keras.models.load_model('../input/lung-ct-segmentation-pretrain/osic_segmentation_model.h5')\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def scale_and_resize(dcm):\n    DIM = 256\n    image = dcm.pixel_array\n    image = ((image - np.min(image)) / (np.max(image) - np.min(image)) * 255).astype(np.uint8)\n\n    if image.shape[0] != 512 or image.shape[1] != 512:\n        old_x, old_y = image.shape[0], image.shape[1]\n        x = (image.shape[0] - 512) // 2\n        y = (image.shape[1] - 512) // 2\n        image = image[x : old_x-x, y : old_y-y]\n        image = image[:512, :512]\n\n    image = cv2.resize(image, (DIM,DIM), cv2.INTER_AREA)\n    image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)\n    return image/ 255.0","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Calculating volumes"},{"metadata":{},"cell_type":"markdown","source":"The volumes can be retrieved from the data set"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_volume(patient, trace = False):\n    #loading\n    scans = load_scan(INPUT_FOLDER + patient)   \n    stack = np.array([scale_and_resize(s) for s in scans])    \n    \n    #masks\n    pred_masks = model.predict(stack, verbose=0)    \n    pred_masks = (pred_masks>0.5).astype(np.float32)    \n        \n    n = len(scans)\n    volume = []\n    pixelcount = 0    \n\n    #volume of each slice\n    for i in range(n):   \n        pixelfactor = scans[i].pixel_array.shape[0] * scans[i].pixel_array.shape[1] / (pred_masks.shape[1] * pred_masks.shape[2])\n        thickness = float(scans[i].SliceThickness)\n        if (i < n - 1 and hasattr(scans[i], 'SliceLocation') and hasattr(scans[i+1], 'SliceLocation')):\n            thickness = min(abs(scans[i].SliceLocation - scans[i+1].SliceLocation), thickness)        \n        voxelsize = float(scans[i].PixelSpacing[0]) * float(scans[i].PixelSpacing[1]) * thickness\n        pixelcount = np.sum(pred_masks[i].astype('int')) * pixelfactor\n        volume.append(pixelcount * voxelsize)    \n      \n    #linear interpolation between slices with spacing larger than slice thickness\n    totalvolume = 0\n    for i in range(n-1):\n        meanv = (volume[i] + volume[i + 1]) / 2\n        meanth = ((scans[i].SliceThickness + scans[i+1].SliceThickness) / 2)\n        if (hasattr(scans[i], 'SliceLocation') and hasattr(scans[i+1], 'SliceLocation')):\n            meanth = min(abs(scans[i].SliceLocation - scans[i+1].SliceLocation), meanth)\n        distance = meanth if (not hasattr(scans[i], 'SliceLocation') or not hasattr(scans[i+1], 'SliceLocation')) else np.abs(scans[i].SliceLocation - scans[i+1].SliceLocation)\n        totalvolume += volume[i] +  (distance - meanth) * meanv\n\n    totalvolume += volume[-1]\n    \n    del scans\n    del stack\n    del pred_masks\n\n    return totalvolume / (100*100*100) * 1000","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_volumes(patients):\n    volumes = np.zeros(len(patients))\n    count = 0\n    for p in patients:\n        volumes[count] = get_volume(p,False)\n        print(volumes[count])\n        print(count)\n        count += 1      \n        \n    return volumes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"volumes = None\nvolumesPath = '../input/osicpulmonaryfibrosislungvolumes/LungVolumesInterpolated.npy'\n\ntry:\n    volumes = np.load(volumesPath) \nexcept:\n    import tensorflow as tf\n    from sklearn.model_selection import train_test_split\n    from tensorflow.keras.utils import get_custom_objects\n\n    warnings.filterwarnings('ignore')\n    print('Tensorflow version : {}'.format(tf.__version__))\n    \n    model = get_segmentation_model()\n    volumes = get_volumes(patientimages)\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow as tf\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.utils import get_custom_objects\n\nwarnings.filterwarnings('ignore')\nprint('Tensorflow version : {}'.format(tf.__version__))\n    \nmodel = get_segmentation_model()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Analysing volumes"},{"metadata":{},"cell_type":"markdown","source":"* If the assumption made in the introduction is correct the calculated volumes should correlate linearly with the maximum FVC values"},{"metadata":{"trusted":true},"cell_type":"code","source":"ROOT = '../input/osic-pulmonary-fibrosis-progression'\ntrain_df = pd.read_csv(f'{ROOT}/train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.drop_duplicates(subset=['Patient','Weeks'], keep = False, inplace = True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"groupedfvc = groupedbypatient.FVC.apply(list).reset_index()['FVC']\ngroupedprecents = groupedbypatient.Percent.apply(list).reset_index()['Percent']\ngroupedweeks = groupedbypatient.Weeks.apply(list).reset_index()['Weeks']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"maxfvc = np.array([max(groupedfvc[i]) for i in range(groupedfvc.shape[0])])\nmaxpercent = np.array([max(groupedprecents[i]) for i in range(groupedprecents.shape[0])])\nminweeks = np.array([min(groupedweeks[i]) for i in range(groupedweeks.shape[0])])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.scatter(maxfvc,volumes)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* The multiple clusters in the scatter plot suggest that some aspect was not properly included to get consistent volumes for all patients\n* The large cluster at the bottom however suggests that there is some value to the assumption, let's look at it closer"},{"metadata":{"trusted":true},"cell_type":"code","source":"maskfraction = (maxfvc / volumes) < 0.8\nmaskfraction = maskfraction & ((maxfvc / volumes) > 0.4)\nmaskvolume = volumes < 6000\nmaskfv = maskfraction & maskvolume","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.scatter(maxfvc[maskfv],volumes[maskfv])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Clearly there is a linear correlation\n* This supports the thesis that FVC/Volume should be a better indicator for the state of the disease, than FVC alone\n* Let's investigate how the FVC/Volume correlates with Percent"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.scatter(maxfvc[maskfv]/volumes[maskfv],maxpercent[maskfv])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Apparently there is no clear correlation\n* This suggests, that the two quantities do not describe the lung's state of fibrosis equivalently"},{"metadata":{"trusted":true},"cell_type":"code","source":"patientimagesmasked = patientimages[maskfv]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Defining health using calculated volumes\nhealth = maxfvc[maskfv] / volumes[maskfv]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Defining health using Percent\nhealth = maxpercent[maskfv]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Testing the health metric\npercentmasked = maxpercent[maskfv]\nweeksmasked = minweeks[maskfv]\nmhpercent = percentmasked[np.max(health) == health][0]\nmcpercent = percentmasked[np.min(health) == health][0]\nmhminweek = weeksmasked[np.max(health) == health][0]\nmcminweek = weeksmasked[np.min(health) == health][0]\nprint('Most healthy patient by estimation has a percent of ' + str(mhpercent))\nprint('Most healthy patient by estimation has a min week of ' + str(mhminweek))\nprint('Most critical patient by estimation has a percent of ' + str(mcpercent))\nprint('Most critical patient by estimation has a min week of ' + str(mcminweek))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mosthealthypatient = patientimagesmasked[np.max(health) == health][0]\nmostcriticalpatient = patientimagesmasked[np.min(health) == health][0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mhscan = load_scan(INPUT_FOLDER + mosthealthypatient)\nplt.imshow(mhscan[len(mhscan) // 2].pixel_array)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mcscan = load_scan(INPUT_FOLDER + mostcriticalpatient)\nplt.imshow(mcscan[len(mcscan) // 2].pixel_array)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# How do the metrics influence image classification?"},{"metadata":{},"cell_type":"markdown","source":"* The idea is to divide the weeks into intervals with enough training data for a neural network"},{"metadata":{},"cell_type":"markdown","source":"* Determining the intervals"},{"metadata":{"trusted":true},"cell_type":"code","source":"lastw = 0\nfor i in range(weeksmasked.shape[0]):\n    if np.max(weeksmasked[i]) > lastw:\n        lastw = np.max(weeksmasked[i])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"minw = -100 #week marking an interval\nmaxw = 0 #week marking an interval\ninterval = np.zeros((2,weeksmasked.shape[0])) #intervals\nindex = 0\nminamount = 10#minmum amount of patients per interval\n\nj = maxw\nwhile j <= lastw + 1:\n    count = 0\n    while(count < minamount and maxw <= lastw + 1):\n        count = 0\n        for i in range(weeksmasked.shape[0]):\n            mask1 = minw <= weeksmasked[i]\n            mask2 = weeksmasked[i] < maxw\n            r = weeksmasked[i][mask1 & mask2]   \n            if r.shape[0] > 0:\n                count += 1\n        \n        maxw += 1\n        \n        \n    interval[0,index] = minw\n    interval[1,index] = maxw\n    index += 1\n    minw = maxw\n    maxw = minw + 1\n    j = maxw","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = np.zeros((interval.shape[0],interval.shape[1])).astype('bool')\nmask[0,:] = interval[1,:] > 0\nmask[1,:] = mask[0,:]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"interval = interval[mask].reshape(2,int(interval[mask].shape[0]/2)).astype('int')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Intervals:')\ninterval","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"columnlist = ['Patient']\nfor i in range(interval.shape[1]):\n    columnlist.append(str(interval[0,i]) + \"_\" + str(interval[1,i]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fvcmasked = np.array(groupedfvc[maskfv])\nvolumesmasked = volumes[maskfv]\npercentsmasked = np.array(groupedprecents[maskfv])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fvcpervolintervalmeans_df = None\nfor i in range(len(patientimagesmasked)):\n    row = list()\n    patient = patientimagesmasked[i]\n    row.append(patient)\n    for j in range(interval.shape[1]):       \n        maskinterval = (weeksmasked[i] >= interval[0,j]) \n        maskinterval2 = weeksmasked[i] < (interval[1,j] - 1)         \n        mean = (np.mean(fvcmasked[i][maskinterval2 & maskinterval])) / volumesmasked[i]\n        row.append(mean)\n   \n    df = pd.DataFrame([row], columns=columnlist)\n    \n    if(i == 0):\n        fvcpervolintervalmeans_df = df\n    else:\n        fvcpervolintervalmeans_df = pd.concat([fvcpervolintervalmeans_df,df])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_intervalmeans(fvcperv):\n    intervalmeans_df = None\n    for i in range(len(patientimagesmasked)):\n        row = list()\n        patient = patientimagesmasked[i]\n        row.append(patient)\n        for j in range(interval.shape[1]):       \n            maskinterval = (weeksmasked[i] >= interval[0,j]) \n            maskinterval2 = weeksmasked[i] < (interval[1,j] - 1)         \n            mean = (np.mean(fvcmasked[i][maskinterval2 & maskinterval])) / volumesmasked[i] if fvcperv else (np.mean(percentsmasked[i][maskinterval2 & maskinterval]))\n            row.append(mean)\n\n        df = pd.DataFrame([row], columns=columnlist)\n\n        if(i == 0):\n            intervalmeans_df = df\n        else:\n            intervalmeans_df = pd.concat([intervalmeans_df,df])\n            \n    return intervalmeans_df        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fvcpervolintervalmeans_df = get_intervalmeans(True)\npercentintervalmeans_df = get_intervalmeans(False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fvcpervolintervalmeans_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Choosing the six slices with the largest area for training the classifier"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_largest_slices(nslices, patient):\n    scans = load_scan(INPUT_FOLDER + patient)   \n    stack = np.array([scale_and_resize(s) for s in scans])    \n    pred_masks = model.predict(stack, verbose=0)    \n    pred_masks = (pred_masks>0.5).astype(np.float32)\n    ps = np.sum(pred_masks, axis = 1)\n    ps = np.sum(ps, axis = 1)\n    ps = ps.reshape(ps.shape[0])\n    \n    del scans\n    del stack\n    del pred_masks\n    \n    ps2 = ps.copy() \n    indices = []\n    indiceshelper = np.arange(0, ps.shape[0])\n    for i in range(nslices):\n        maxtemp = np.max(ps2)\n        indices.append(indiceshelper[ps == maxtemp][0])\n        ps2[ps2 == maxtemp] = -1\n        \n    return indices\n   ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"intervalmeanspath = '../input/osicintervalmeansandlargestslices/intervalmeans_df.csv'\n\ntry:\n    largestslices_df = pd.read_csv(intervalmeanspath)\nexcept:\n    nslices = 6\n    largestslices = []\n    count = 0\n    for p in intervalmeans_df['Patient']:\n        print(count)\n        count += 1\n        largestslices.append(get_largest_slices(nslices, p))\n\n    intervalmeans_df['LargestSlices'] = largestslices    \n    intervalmeans_df.to_csv('intervalmeans_df',index=False)\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_files_names(interval, intervalmeans_df, getlabels = True):\n   \n    fnames = []\n    labels = []\n    for p in intervalmeans_df['Patient']:\n        if getlabels:\n            if math.isnan(intervalmeans_df[intervalmeans_df['Patient'] == p][interval].to_list()[0]):\n                continue\n        sa = [int(s.split(\".\")[0]) for s in os.listdir(INPUT_FOLDER + p)]\n        sa.sort()\n        largestslices = largestslices_df[largestslices_df['Patient'] == p]['LargestSlices']     \n        print(largestslices)\n        largestslices = largestslices.to_list()[0].strip('][').split(', ') if type(largestslices.to_list()[0]) == str else largestslices[0]    \n        print(largestslices)\n        for s in largestslices:  \n            #print(type(s))\n            #print(s)\n            fnames.append(p + '/' + str(sa[int(s)]) + '.dcm')\n            if getlabels: labels.append(intervalmeans_df[intervalmeans_df['Patient'] == p][interval].to_list()[0])   \n    \n    \n    return fnames, labels","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fnames, labelsfvcperv = get_files_names(fvcpervolintervalmeans_df.columns[2], fvcpervolintervalmeans_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fnames, labelspercent = get_files_names(fvcpervolintervalmeans_df.columns[2], percentintervalmeans_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install torch==1.6.0+cu101 torchvision==0.7.0+cu101 -f https://download.pytorch.org/whl/torch_stable.html\n!pip install fastai==2.0.9","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from fastai.vision.all import *\nfrom fastai.data.all import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_image_file_paths(inputfolder):\n    return [inputfolder+f for f in fnames]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_labels_fvcperv(fname):    \n    return np.array(labelsfvcperv)[np.array(fnames) == (fname).split('/')[-2] + '/' + (fname).split('/')[-1]]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_labels_percent(fname):    \n    return np.array(labelspercent)[np.array(fnames) == (fname).split('/')[-2] + '/' + (fname).split('/')[-1]] / 100","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_pixels_hu(scans):\n    \"\"\"\n    Converts raw images to Hounsfield Units (HU).\n    \n    Parameters: scans (Raw images)\n    \n    Returns: image (NumPy array)\n    \"\"\"\n    \n    image = np.stack([s.pixel_array for s in scans])\n    image = image.astype(np.int16)\n\n    # Since the scanning equipment is cylindrical in nature and image output is square,\n    # we set the out-of-scan pixels to 0\n    image[image == -2000] = 0\n    \n    \n    # HU = m*P + b\n    intercept = scans[0].RescaleIntercept\n    slope = scans[0].RescaleSlope\n    \n    if slope != 1:\n        image = slope * image.astype(np.float64)\n        image = image.astype(np.int16)\n        \n    image += np.int16(intercept)\n    \n    return np.array(image, dtype=np.int16)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create(fn):            \n    img1 = pydicom.read_file(fn)\n    img1 = get_pixels_hu([img1])\n    img1 = PILImage(Image.fromarray(img1[0], mode=None))\n    img1 = Resize(224)(img1)       \n        \n    return img1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def CustomImageBlock(): return TransformBlock(type_tfms=create, batch_tfms=IntToFloatTensor)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dblockfvcperv = DataBlock(blocks    = (CustomImageBlock, RegressionBlock),\n                   get_items = get_image_file_paths,\n                   get_y     = get_labels_fvcperv,\n                   splitter  = RandomSplitter())\ndsets = dblockfvcperv.datasets(INPUT_FOLDER)\ndsets.train[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dblockpercent = DataBlock(blocks    = (CustomImageBlock, RegressionBlock),\n                   get_items = get_image_file_paths,\n                   get_y     = get_labels_percent,\n                   splitter  = RandomSplitter())\ndsets = dblockpercent.datasets(INPUT_FOLDER)\ndsets.train[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dlsfvcperv = dblockfvcperv.dataloaders(INPUT_FOLDER)\ndlspercent = dblockpercent.dataloaders(INPUT_FOLDER)\ndlspercent.cuda().one_batch()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"torch.cuda.is_available()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learnpercent = cnn_learner(dlspercent.cuda(), resnet34, metrics=error_rate)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learnpercent.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learnpercent.fine_tune(10,1e-2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learnfvcperv = cnn_learner(dlsfvcperv.cuda(), resnet34, metrics=error_rate)\nlearnfvcperv.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learnfvcperv.fine_tune(10,1e-2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* The low valid_loss shows, that both quantities can be extracted from the images\n* Let's see what they predict on a test set"},{"metadata":{"trusted":true},"cell_type":"code","source":"ntest = 10","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"testpatients = patientimages[np.bitwise_not(maskfv)][10:10+ntest]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"nslices = 6\nlargestslices = []\ncount = 0\nfor p in testpatients:\n    print(count)\n    count += 1\n    #print(INPUT_FOLDER + patient)\n    largestslices.append(get_largest_slices(nslices, p))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fnamestest = []    \nfor p in testpatients:    \n    sa = [int(s.split(\".\")[0]) for s in os.listdir(INPUT_FOLDER + p)]\n    sa.sort()\n    lp = np.array(largestslices)[testpatients == p]    \n    lp = lp[0]\n    for s in lp:  \n        #print(type(s))\n        #print(s)\n        fnamestest.append(p + '/' + str(sa[int(s)]) + '.dcm')    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predsfvcpervol = []\npredspercent = []\nfor fn in fnamestest:\n    predsfvcpervol.append(learnfvcperv.predict(create(INPUT_FOLDER+fn)))\n    predspercent.append(learnpercent.predict(create(INPUT_FOLDER+fn)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predsfvcpervol = [p[0][0] for p in predsfvcpervol]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predsfvcpervolmeaned = []\nfor i in range(len(predsfvcpervol) // 6):\n    predsfvcpervolmeaned.append(np.mean(predsfvcpervol[i*6:(i+1)*6]))    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(predsfvcpervolmeaned)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predspercent = [p[0][0] for p in predspercent]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predspercentmeaned = []\nfor i in range(len(predspercent) // 6):\n    predspercentmeaned.append(np.mean(predspercent[i*6:(i+1)*6]))    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(predspercentmeaned)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predsindexhelper = np.arange(0,ntest)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"minpercentim = pydicom.read_file(INPUT_FOLDER + fnamestest[predsindexhelper[np.array(predspercentmeaned) == min(predspercentmeaned)][0]*6]).pixel_array\nplt.imshow(minpercentim)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"maxpercentim = pydicom.read_file(INPUT_FOLDER + fnamestest[predsindexhelper[np.array(predspercentmeaned) == max(predspercentmeaned)][0]*6]).pixel_array\nplt.imshow(maxpercentim)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"minfvcpervolim = pydicom.read_file(INPUT_FOLDER + fnamestest[predsindexhelper[np.array(predsfvcpervolmeaned) == min(predsfvcpervolmeaned)][0]*6]).pixel_array\nplt.imshow(minfvcpervolim)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"maxfvcpervolim = pydicom.read_file(INPUT_FOLDER + fnamestest[predsindexhelper[np.array(predsfvcpervolmeaned) == max(predsfvcpervolmeaned)][0]*6]).pixel_array\nplt.imshow(maxfvcpervolim)","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}