{"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":"# CAPSTONE PROJECT -  Pneumonia Detection System","metadata":{"id":"wU66WuEySsFk"}},{"cell_type":"markdown","source":"<b>The Real Problem : </b>  \n- What is Pneumonia?  \nPneumonia is an infection in one or both lungs. Bacteria, viruses, and fungi cause it. The infection causes inflammation in the air sacs in your lungs, which are called alveoli. Pneumonia accounts for over 15% of all deaths of children under 5 years old internationally. In 2017, 920,000 children under the age of 5 died from the disease. It requires review of a chest radiograph (CXR) by highly trained specialists and confirmation through clinical history, vital signs and laboratory exams. Pneumonia usually manifests as an area or areas of increased opacity on CXR. However, the diagnosis of pneumonia on CXR is complicated because of a number of other conditions in the lungs such as fluid overload (pulmonary edema), bleeding, volume loss (atelectasis or collapse), lung cancer, or post- radiation or surgical changes. Outside of the lungs, fluid in the pleural space (pleural effusion) also appears as increased opacity on CXR. When available, comparison of CXRs of the patient taken at different time points and correlation with clinical symptoms and history are helpful in making the diagnosis. CXRs are the most commonly performed diagnostic imaging study. A number of factors such as positioning of the patient and depth of inspiration can alter the appearance of the CXR, complicating interpretation further. In addition, clinicians are faced with reading high volumes of images every shift.\n  \n- Pneumonia Detectiontion  \nNow to detect Pneumonia we need to detect Inflammation of the lungs. In this project, you’re challenged to build an algorithm to detect a visual signal for pneumonia in medical images. Specifically, your algorithm needs to automatically locate lung opacities on chest radiographs.\n\n- Business Domain Value  \nAutomating Pneumonia screening in chest radiographs, providing affected area details through bounding box. Assist physicians to make better clinical decisions or even replace human judgement in certain functional areas of healthcare (eg, radiology). Guided by relevant clinical questions, powerful AI techniques can unlock clinically relevant information hidden in the massive amount of data, which in turn can assist clinical decision making.","metadata":{"id":"50yJuL1_dzC-"}},{"cell_type":"markdown","source":"<b>Project Description</b>  \n- In this capstone project, the goal is to build a pneumonia detection system, to locate the position of inflammation in an image. Tissues with sparse material, such as lungs which are full of air, do not absorb the X-rays and appear black in the image. Dense tissues such as bones absorb X-rays and appear white in the image. While we are theoretically detecting “lung opacities”, there are lung opacities that are not pneumonia related. In the data, some of these are labeled “Not Normal No Lung Opacity”. This extra third class indicates that while pneumonia was determined not to be present, there was nonetheless some type of abnormality on the image and oftentimes this finding may mimic the appearance of true pneumonia. Dicom original images: - Medical images are stored in a special format called DICOM files (*.dcm). They contain a combination of header metadata as well as underlying raw image arrays for pixel data.   \nDetails about the data and dataset files are given in below link :-  \nhttps://www.kaggle.com/c/rsna-pneumonia-detection-challenge/data","metadata":{"id":"ZPGNK3IZfSsX"}},{"cell_type":"markdown","source":"### 1. Pre-Processing, Data Visualization, EDA :-\n- Exploring the given Data files, classes and images of different classes.\n- Dealing with missing values\n- Visualization of differentclasses\n- Analysis from the visualization of different classes.","metadata":{"id":"opIqQF3QgFLz"}},{"cell_type":"markdown","source":"<b>Install libraries required</b>","metadata":{"id":"4Yc6tD47gde-"}},{"cell_type":"code","source":"# Required to open dcm images\n!pip install pydicom","metadata":{"id":"ZzRo_7lsRKji","outputId":"d2b36a5a-c99a-4976-f589-b3446a1935f6","execution":{"iopub.status.busy":"2022-06-25T04:54:12.900005Z","iopub.execute_input":"2022-06-25T04:54:12.900917Z","iopub.status.idle":"2022-06-25T04:54:23.185284Z","shell.execute_reply.started":"2022-06-25T04:54:12.900802Z","shell.execute_reply":"2022-06-25T04:54:23.184292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Import necesaary modules</b>","metadata":{"id":"4fKlzqY9gjyi"}},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\n#from google.colab import drive\nimport pydicom\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nimport tensorflow as tf\nimport tqdm\nfrom keras.preprocessing.image import ImageDataGenerator\nimport random\nfrom sklearn.metrics import accuracy_score, confusion_matrix, classification_report, f1_score, recall_score, precision_score\nfrom imblearn.under_sampling import RandomUnderSampler\nfrom shutil import copyfile, rmtree\nimport random","metadata":{"id":"Ujo5bYtiU0bE","execution":{"iopub.status.busy":"2022-06-26T01:32:37.763532Z","iopub.execute_input":"2022-06-26T01:32:37.764087Z","iopub.status.idle":"2022-06-26T01:32:45.510693Z","shell.execute_reply.started":"2022-06-26T01:32:37.763957Z","shell.execute_reply":"2022-06-26T01:32:45.509797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed = 7\nnp.random.seed(seed)","metadata":{"id":"XvTSaYQ_Bvk4","execution":{"iopub.status.busy":"2022-06-26T01:32:45.512622Z","iopub.execute_input":"2022-06-26T01:32:45.513515Z","iopub.status.idle":"2022-06-26T01:32:45.519117Z","shell.execute_reply.started":"2022-06-26T01:32:45.513459Z","shell.execute_reply":"2022-06-26T01:32:45.518237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Mount google drive at '/mnt'</b>","metadata":{"id":"dhHsNhyIgqO8"}},{"cell_type":"code","source":"#drive.mount('/mnt')","metadata":{"id":"pvOlmt3xU321","outputId":"1f1217a0-9e4d-4ddb-ec0e-164352dda7f0","execution":{"iopub.status.busy":"2022-06-25T05:15:33.555963Z","iopub.execute_input":"2022-06-25T05:15:33.556344Z","iopub.status.idle":"2022-06-25T05:15:33.560457Z","shell.execute_reply.started":"2022-06-25T05:15:33.55631Z","shell.execute_reply":"2022-06-25T05:15:33.559378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Below steps are required to download dataset from kaggle</b>","metadata":{"id":"xIo_kGWegw7F"}},{"cell_type":"code","source":"#!mkdir /root/.kaggle\n#!cp /mnt/MyDrive/Dataset/kaggle.json /root/.kaggle/","metadata":{"id":"_O-VaeN7WZzl","execution":{"iopub.status.busy":"2022-06-25T05:15:34.24101Z","iopub.execute_input":"2022-06-25T05:15:34.241788Z","iopub.status.idle":"2022-06-25T05:15:34.246036Z","shell.execute_reply.started":"2022-06-25T05:15:34.241752Z","shell.execute_reply":"2022-06-25T05:15:34.244462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp -r /kaggle/input/rsna-pneumonia-detection-challenge/ /kaggle/working/","metadata":{"execution":{"iopub.status.busy":"2022-06-26T01:32:53.997009Z","iopub.execute_input":"2022-06-26T01:32:53.997360Z","iopub.status.idle":"2022-06-26T01:36:56.009161Z","shell.execute_reply.started":"2022-06-26T01:32:53.997330Z","shell.execute_reply":"2022-06-26T01:36:56.007963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATASET_BASE_DIR = '/kaggle/working/rsna-pneumonia-detection-challenge/'","metadata":{"id":"rHwfYZoQyWev","execution":{"iopub.status.busy":"2022-06-26T01:36:56.011932Z","iopub.execute_input":"2022-06-26T01:36:56.012326Z","iopub.status.idle":"2022-06-26T01:36:56.016900Z","shell.execute_reply.started":"2022-06-26T01:36:56.012287Z","shell.execute_reply":"2022-06-26T01:36:56.015898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.chdir(DATASET_BASE_DIR)","metadata":{"id":"FjiJFuhZVNJ1","execution":{"iopub.status.busy":"2022-06-26T01:36:56.018240Z","iopub.execute_input":"2022-06-26T01:36:56.018787Z","iopub.status.idle":"2022-06-26T01:36:56.034081Z","shell.execute_reply.started":"2022-06-26T01:36:56.018751Z","shell.execute_reply":"2022-06-26T01:36:56.033245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Download dataset from kaggle</b>","metadata":{"id":"bA3XXruvhM87"}},{"cell_type":"code","source":"#!kaggle competitions download -c rsna-pneumonia-detection-challenge","metadata":{"id":"0UWwxnIwVo--","outputId":"d4a05bbf-d465-4148-ab17-ae85ab7cceb3","execution":{"iopub.status.busy":"2022-06-25T04:57:38.35943Z","iopub.execute_input":"2022-06-25T04:57:38.359907Z","iopub.status.idle":"2022-06-25T04:57:38.366756Z","shell.execute_reply.started":"2022-06-25T04:57:38.359871Z","shell.execute_reply":"2022-06-25T04:57:38.365943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!ls","metadata":{"id":"NenkfIE_j4SO","outputId":"17908cb8-46b0-4a12-8c49-a63283803137","execution":{"iopub.status.busy":"2022-06-25T04:57:38.370896Z","iopub.execute_input":"2022-06-25T04:57:38.371262Z","iopub.status.idle":"2022-06-25T04:57:38.375404Z","shell.execute_reply.started":"2022-06-25T04:57:38.371238Z","shell.execute_reply":"2022-06-25T04:57:38.374494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!unzip -q rsna-pneumonia-detection-challenge.zip","metadata":{"id":"ZvPeCi5oVrMV","execution":{"iopub.status.busy":"2022-06-25T04:57:38.3772Z","iopub.execute_input":"2022-06-25T04:57:38.377743Z","iopub.status.idle":"2022-06-25T04:57:38.384347Z","shell.execute_reply.started":"2022-06-25T04:57:38.377653Z","shell.execute_reply":"2022-06-25T04:57:38.383479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls","metadata":{"id":"7Yf7c3lTXqPd","outputId":"add7fa26-3c83-43ca-b585-b5e422604c13","execution":{"iopub.status.busy":"2022-06-26T01:36:56.037394Z","iopub.execute_input":"2022-06-26T01:36:56.037675Z","iopub.status.idle":"2022-06-26T01:36:56.759577Z","shell.execute_reply.started":"2022-06-26T01:36:56.037652Z","shell.execute_reply":"2022-06-26T01:36:56.758495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- There are six files in the dataset.  \n- Files 'stage_2_train_labels.csv', 'stage_2_detailed_class_info.csv' and directory 'stage_2_train_images' are of our interest. Rest all can be ignored.","metadata":{"id":"ELgZTnl-hTKG"}},{"cell_type":"markdown","source":"<b>Read stage_2_train_labels.csv</b>","metadata":{"id":"ZIcf85bmjFO1"}},{"cell_type":"code","source":"train_labels = pd.read_csv('./stage_2_train_labels.csv')","metadata":{"id":"tHnLMb5AV30K","execution":{"iopub.status.busy":"2022-06-26T01:36:56.761543Z","iopub.execute_input":"2022-06-26T01:36:56.762009Z","iopub.status.idle":"2022-06-26T01:36:56.819640Z","shell.execute_reply.started":"2022-06-26T01:36:56.761969Z","shell.execute_reply":"2022-06-26T01:36:56.818697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Dataframe Shape : {train_labels.shape}')","metadata":{"id":"5G8YEVgbWEzJ","outputId":"14c86fd5-ffe7-4108-929e-9151b55ea792","execution":{"iopub.status.busy":"2022-06-26T01:36:56.820956Z","iopub.execute_input":"2022-06-26T01:36:56.821786Z","iopub.status.idle":"2022-06-26T01:36:56.827276Z","shell.execute_reply.started":"2022-06-26T01:36:56.821746Z","shell.execute_reply":"2022-06-26T01:36:56.826416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels.info()","metadata":{"id":"5O7L6hgKEtFJ","outputId":"9e69a1f2-434d-4290-ac1d-9be10a38cdba","execution":{"iopub.status.busy":"2022-06-26T01:36:56.828577Z","iopub.execute_input":"2022-06-26T01:36:56.829353Z","iopub.status.idle":"2022-06-26T01:36:56.872027Z","shell.execute_reply.started":"2022-06-26T01:36:56.829313Z","shell.execute_reply":"2022-06-26T01:36:56.870958Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- 'Target' specifies whether the patient has pneumonia or not.\n- x,y, width and height must be the location of pneumonia patches in x-ray.\n- There are null entries in the x, y, width and height columns.","metadata":{"id":"ludDYzxAoRaw"}},{"cell_type":"code","source":"train_labels.head(10)","metadata":{"id":"zctuyFpPoI9n","outputId":"558817ea-f5d5-49c7-9597-fa19c98a94e9","execution":{"iopub.status.busy":"2022-06-26T01:36:56.873575Z","iopub.execute_input":"2022-06-26T01:36:56.874560Z","iopub.status.idle":"2022-06-26T01:36:56.901548Z","shell.execute_reply.started":"2022-06-26T01:36:56.874495Z","shell.execute_reply":"2022-06-26T01:36:56.900545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels.sample(5)","metadata":{"id":"gWDwjzAZgt20","outputId":"9a9d53c6-05b8-438d-a8b9-ab536a177293","execution":{"iopub.status.busy":"2022-06-26T01:36:56.903106Z","iopub.execute_input":"2022-06-26T01:36:56.903756Z","iopub.status.idle":"2022-06-26T01:36:56.921211Z","shell.execute_reply.started":"2022-06-26T01:36:56.903703Z","shell.execute_reply":"2022-06-26T01:36:56.920267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- It seems that x, y, width and height are null whereever 'Target' is 0 which makes sense since there should be no patches if the patient doesn't have pneumonia. Thus we can safely keep x, y, width and height 0 for null entries.","metadata":{"id":"_yjwIVJ-mhhg"}},{"cell_type":"code","source":"train_labels['x'] = train_labels['x'].fillna(0)\ntrain_labels['y'] = train_labels['y'].fillna(0)\ntrain_labels['width'] = train_labels['width'].fillna(0)\ntrain_labels['height'] = train_labels['height'].fillna(0)","metadata":{"id":"iaqYPjf08b3Z","execution":{"iopub.status.busy":"2022-06-26T01:36:56.924898Z","iopub.execute_input":"2022-06-26T01:36:56.925173Z","iopub.status.idle":"2022-06-26T01:36:56.935081Z","shell.execute_reply.started":"2022-06-26T01:36:56.925147Z","shell.execute_reply":"2022-06-26T01:36:56.933985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Load 'stage_2_detailed_class_info.csv'</b>","metadata":{"id":"Gngg0lrav7dp"}},{"cell_type":"code","source":"class_info = pd.read_csv('./stage_2_detailed_class_info.csv')","metadata":{"id":"JtHyg67TWGdI","execution":{"iopub.status.busy":"2022-06-26T01:36:56.936723Z","iopub.execute_input":"2022-06-26T01:36:56.937370Z","iopub.status.idle":"2022-06-26T01:36:56.975526Z","shell.execute_reply.started":"2022-06-26T01:36:56.937331Z","shell.execute_reply":"2022-06-26T01:36:56.974737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Dataframe Shape : {class_info.shape}')","metadata":{"id":"3EMacqMqwGv_","outputId":"d1fd956b-7940-487f-b181-a4d4d2101882","execution":{"iopub.status.busy":"2022-06-26T01:36:56.976855Z","iopub.execute_input":"2022-06-26T01:36:56.977279Z","iopub.status.idle":"2022-06-26T01:36:56.984876Z","shell.execute_reply.started":"2022-06-26T01:36:56.977243Z","shell.execute_reply":"2022-06-26T01:36:56.983449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_info.info()","metadata":{"id":"zKisWNkjwNGd","outputId":"945b94df-b5aa-4c35-97c8-3472395b03b2","execution":{"iopub.status.busy":"2022-06-26T01:36:56.987513Z","iopub.execute_input":"2022-06-26T01:36:56.988263Z","iopub.status.idle":"2022-06-26T01:36:57.006507Z","shell.execute_reply.started":"2022-06-26T01:36:56.988224Z","shell.execute_reply":"2022-06-26T01:36:57.004790Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_info.head(5)","metadata":{"id":"krJ7wwDVwavt","outputId":"7a670f75-2491-4501-a8ae-6aa0a996e1ec","execution":{"iopub.status.busy":"2022-06-26T01:36:57.007938Z","iopub.execute_input":"2022-06-26T01:36:57.010354Z","iopub.status.idle":"2022-06-26T01:36:57.021305Z","shell.execute_reply.started":"2022-06-26T01:36:57.010323Z","shell.execute_reply":"2022-06-26T01:36:57.020173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_info.sample(5)","metadata":{"id":"TTkewcl0we7x","outputId":"9937a6a1-9cf3-471f-ea50-2bb237de53f1","execution":{"iopub.status.busy":"2022-06-26T01:36:57.023424Z","iopub.execute_input":"2022-06-26T01:36:57.024226Z","iopub.status.idle":"2022-06-26T01:36:57.038403Z","shell.execute_reply.started":"2022-06-26T01:36:57.024165Z","shell.execute_reply":"2022-06-26T01:36:57.037179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- 'stage_2_detailed_class_info.csv' specifies the exact class of each patient, i.e., 'Normal', 'Lung Opacity' and 'No Lung Opacity, Not Normal.\n- There are no null values in this dataframe.","metadata":{"id":"9_fd7viowoxY"}},{"cell_type":"markdown","source":"<b>Let's concatenate the two dataframes and use the merged dataframe for further analysis.</b>","metadata":{"id":"NT1ZKsnRxb-7"}},{"cell_type":"code","source":"df = pd.concat([train_labels, class_info['class']], axis = 1)","metadata":{"id":"aryDcw6Bxljl","execution":{"iopub.status.busy":"2022-06-26T01:36:57.040071Z","iopub.execute_input":"2022-06-26T01:36:57.040731Z","iopub.status.idle":"2022-06-26T01:36:57.048692Z","shell.execute_reply.started":"2022-06-26T01:36:57.040692Z","shell.execute_reply":"2022-06-26T01:36:57.047671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Checking shape and info of merged dataframe</b>","metadata":{"id":"f3a6CdLkxsoe"}},{"cell_type":"code","source":"print(f'Dataframe shape : {df.shape}')","metadata":{"id":"Thria3SPyANL","outputId":"b1e75c2e-bf38-43ee-d57c-b4c57b0a2990","execution":{"iopub.status.busy":"2022-06-26T01:36:57.050593Z","iopub.execute_input":"2022-06-26T01:36:57.051474Z","iopub.status.idle":"2022-06-26T01:36:57.057652Z","shell.execute_reply.started":"2022-06-26T01:36:57.051426Z","shell.execute_reply":"2022-06-26T01:36:57.056605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.info()","metadata":{"id":"YpQYI19UyFsC","outputId":"3f08187d-72c6-4e07-f9c2-077a4f485214","execution":{"iopub.status.busy":"2022-06-26T01:36:57.059532Z","iopub.execute_input":"2022-06-26T01:36:57.060316Z","iopub.status.idle":"2022-06-26T01:36:57.081585Z","shell.execute_reply.started":"2022-06-26T01:36:57.060132Z","shell.execute_reply":"2022-06-26T01:36:57.080444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Unique Patient Ids</b>","metadata":{"id":"yvcl1ZOoqSJ-"}},{"cell_type":"code","source":"print('Number of unique Patient Ids :', train_labels['patientId'].unique().shape[0])","metadata":{"id":"OcBYkk7arOdb","outputId":"cb3462dd-1c0f-4ba1-c76e-0c03bee85cdb","execution":{"iopub.status.busy":"2022-06-26T01:36:57.083114Z","iopub.execute_input":"2022-06-26T01:36:57.083824Z","iopub.status.idle":"2022-06-26T01:36:57.096808Z","shell.execute_reply.started":"2022-06-26T01:36:57.083781Z","shell.execute_reply":"2022-06-26T01:36:57.095513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Number of unique patients is different than the number of rows in the dataset. ","metadata":{"id":"6o5b22AcruWO"}},{"cell_type":"markdown","source":"To find out the reason, let's take a look at the any one patient that has multiple rows.","metadata":{"id":"v4Wp_GN2vpNP"}},{"cell_type":"code","source":"df[df['patientId'] == df[df['patientId'].duplicated()]['patientId'].values[0]]","metadata":{"id":"gYWiqUEItFIG","outputId":"beb2bc6b-af38-4c53-fc9a-5efd47123a79","execution":{"iopub.status.busy":"2022-06-26T01:36:57.098329Z","iopub.execute_input":"2022-06-26T01:36:57.099116Z","iopub.status.idle":"2022-06-26T01:36:57.126075Z","shell.execute_reply.started":"2022-06-26T01:36:57.099078Z","shell.execute_reply":"2022-06-26T01:36:57.125215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- The reason of duplicate patientIds is due to the fact that a patient can have multiple pneumonia patches in xray. So we'll keep all the duplicate entries.","metadata":{"id":"aetb4jFIvuRp"}},{"cell_type":"code","source":"def countplot_with_percentage(clm, name = None, xlabel = None):\n  ''' Function to plot a countplot with percentage for each category'''\n  plt.figure(figsize = (10, 5));\n  ax = sns.countplot(x = clm);\n  total = len(clm)\n  for p in ax.patches:\n            percentage = '{:.2f}%'.format(100 * p.get_height()/total)\n            x = p.get_x() + (p.get_width()/2)\n            y = p.get_y() + p.get_height() + 1\n            ax.annotate(percentage, (x,y), horizontalalignment='center');\n  if(name != None):\n    plt.title(f'Countplot - {name}')\n  if (xlabel != None):\n    plt.xlabel(xlabel)\n  plt.show();","metadata":{"id":"ydWe40_vodyx","execution":{"iopub.status.busy":"2022-06-26T01:36:57.127681Z","iopub.execute_input":"2022-06-26T01:36:57.128527Z","iopub.status.idle":"2022-06-26T01:36:57.137736Z","shell.execute_reply.started":"2022-06-26T01:36:57.128486Z","shell.execute_reply":"2022-06-26T01:36:57.136868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Number of pneumonia patches per patient</b>","metadata":{"id":"qmZYAcsxYgoh"}},{"cell_type":"code","source":"df[df['Target'] == 1]['patientId'].value_counts().value_counts()","metadata":{"id":"H9Y0b30QYrqb","outputId":"7b76b94f-a895-4fe7-c0f1-641ec2c65105","execution":{"iopub.status.busy":"2022-06-26T01:36:57.138937Z","iopub.execute_input":"2022-06-26T01:36:57.139757Z","iopub.status.idle":"2022-06-26T01:36:57.161643Z","shell.execute_reply.started":"2022-06-26T01:36:57.139714Z","shell.execute_reply":"2022-06-26T01:36:57.160644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"countplot_with_percentage(df[df['Target'] == 1]['patientId'].value_counts().reset_index()['patientId'], 'No. of Patches', 'Patches per Patient')","metadata":{"id":"6PIblCe-pOMw","outputId":"c84f2ae2-4630-47af-f409-ac64aaaf644e","execution":{"iopub.status.busy":"2022-06-26T01:36:57.163425Z","iopub.execute_input":"2022-06-26T01:36:57.164108Z","iopub.status.idle":"2022-06-26T01:36:57.537113Z","shell.execute_reply.started":"2022-06-26T01:36:57.164055Z","shell.execute_reply":"2022-06-26T01:36:57.536307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- 98% of the patients who have pneumonia have 1 or 2 patches.","metadata":{"id":"nk_39J55mgKF"}},{"cell_type":"markdown","source":"<b>Target distribution</b>","metadata":{"id":"-3vU54VWm5c-"}},{"cell_type":"markdown","source":"Before visualizing target distribution, we'll group the dataframe by patientId to make sure we get the correct target distribution.","metadata":{"id":"O4oZHatmm-Ta"}},{"cell_type":"code","source":"df_grouped = df.groupby('patientId')","metadata":{"id":"oAnHZ8bDn4UP","execution":{"iopub.status.busy":"2022-06-26T01:36:57.540299Z","iopub.execute_input":"2022-06-26T01:36:57.543209Z","iopub.status.idle":"2022-06-26T01:36:57.551075Z","shell.execute_reply.started":"2022-06-26T01:36:57.543165Z","shell.execute_reply":"2022-06-26T01:36:57.549901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_grouped['Target'].aggregate('first').value_counts()","metadata":{"id":"YsBHPLknoFNA","outputId":"d8ec28e2-bd07-4418-8a4d-fffca040f1c1","execution":{"iopub.status.busy":"2022-06-26T01:36:57.554554Z","iopub.execute_input":"2022-06-26T01:36:57.554993Z","iopub.status.idle":"2022-06-26T01:36:57.626411Z","shell.execute_reply.started":"2022-06-26T01:36:57.554957Z","shell.execute_reply":"2022-06-26T01:36:57.625487Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"countplot_with_percentage(df_grouped['Target'].aggregate('first'), 'Target')","metadata":{"id":"A-6Gm2-KlBfz","outputId":"1340564a-e99e-4a3a-c1f5-14dd8b33cf31","execution":{"iopub.status.busy":"2022-06-26T01:36:57.630601Z","iopub.execute_input":"2022-06-26T01:36:57.631030Z","iopub.status.idle":"2022-06-26T01:36:57.872529Z","shell.execute_reply.started":"2022-06-26T01:36:57.630994Z","shell.execute_reply":"2022-06-26T01:36:57.871704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Dataset is highly imbalanced with respect to 'Target' column.\n- Only 22.5% of patients in dataset have pneumonia.","metadata":{"id":"Ihbzale0sFYc"}},{"cell_type":"markdown","source":"<b>Class Distribution</b>","metadata":{"id":"QrqSBwR_rhMn"}},{"cell_type":"code","source":"df_grouped['class'].aggregate('first').value_counts()","metadata":{"id":"Q0nG_3j3rpfX","outputId":"b8eb08e9-237b-488b-d3b7-debad605ce74","execution":{"iopub.status.busy":"2022-06-26T01:36:57.877145Z","iopub.execute_input":"2022-06-26T01:36:57.879498Z","iopub.status.idle":"2022-06-26T01:36:57.906680Z","shell.execute_reply.started":"2022-06-26T01:36:57.879438Z","shell.execute_reply":"2022-06-26T01:36:57.903786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"countplot_with_percentage(df_grouped['class'].aggregate('first'), 'Class')","metadata":{"id":"1pOZ5QFhrgqe","outputId":"4bfbf507-076e-478a-cfeb-1e9b0ca3f0bb","execution":{"iopub.status.busy":"2022-06-26T01:36:57.914762Z","iopub.execute_input":"2022-06-26T01:36:57.918043Z","iopub.status.idle":"2022-06-26T01:36:58.140261Z","shell.execute_reply.started":"2022-06-26T01:36:57.918000Z","shell.execute_reply":"2022-06-26T01:36:58.139417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- 44% of the records in dataset do not have lung opacity but still X-ray is not normal.","metadata":{"id":"fwMpqP2xmDw1"}},{"cell_type":"markdown","source":"<b>Exploring the dcm files</b>","metadata":{"id":"0N19RDcJm5Tf"}},{"cell_type":"markdown","source":"As mentioned in the project description, the image files have .dcm extension.  \nThe DCM file extension is used for DICOM which stands for Digital Imaging and Communications in Medicine. This is the common file format used to store medical imaging data when a patient undergoes a CT, MRI, PET, UltraSound, and many other types of medical scans. They contain a combination of header metadata as well as underlying raw image arrays for pixel data.","metadata":{"id":"70ONrMGG6QIM"}},{"cell_type":"code","source":"TRAIN_IMAGES_BASE_PATH = os.path.join(DATASET_BASE_DIR,'stage_2_train_images/')","metadata":{"id":"icAkTUvzsVv6","execution":{"iopub.status.busy":"2022-06-26T01:36:58.141697Z","iopub.execute_input":"2022-06-26T01:36:58.142321Z","iopub.status.idle":"2022-06-26T01:36:58.147338Z","shell.execute_reply.started":"2022-06-26T01:36:58.142283Z","shell.execute_reply":"2022-06-26T01:36:58.146487Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Listing first ten files from 'stage_2_train_images' directory","metadata":{"id":"-2g2wASusov6"}},{"cell_type":"code","source":"os.listdir(TRAIN_IMAGES_BASE_PATH)[0:10]","metadata":{"id":"d5VsbqS8n3tI","outputId":"a7bd1678-21cf-468f-9330-4be0cfd467d0","execution":{"iopub.status.busy":"2022-06-26T01:36:58.148682Z","iopub.execute_input":"2022-06-26T01:36:58.149277Z","iopub.status.idle":"2022-06-26T01:36:58.179236Z","shell.execute_reply.started":"2022-06-26T01:36:58.149240Z","shell.execute_reply":"2022-06-26T01:36:58.178437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The filenames in the images directory correspond to the pateintIds. The same patientIds must exist in dataset as well.","metadata":{"id":"2KDYlvHmtQib"}},{"cell_type":"markdown","source":"Let's open any one file and see how it looks. pydicom is the python library that undertands the .dcm file format. We have already installed it in the beginning of notebook.","metadata":{"id":"acZtoktwtwHM"}},{"cell_type":"code","source":"# Patient with normal X-ray\ndcm_img_file = pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, '984afed3-af7c-45d3-b202-4788f9522b28.dcm'))","metadata":{"id":"p7xuqWP5jO7V","execution":{"iopub.status.busy":"2022-06-26T01:36:58.180499Z","iopub.execute_input":"2022-06-26T01:36:58.180877Z","iopub.status.idle":"2022-06-26T01:36:58.190187Z","shell.execute_reply.started":"2022-06-26T01:36:58.180840Z","shell.execute_reply":"2022-06-26T01:36:58.189465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"type(dcm_img_file)","metadata":{"id":"fjxYyj0veb7w","outputId":"e7f1f2b7-5334-41c8-c81c-11652b502c5b","execution":{"iopub.status.busy":"2022-06-26T01:36:58.191515Z","iopub.execute_input":"2022-06-26T01:36:58.191992Z","iopub.status.idle":"2022-06-26T01:36:58.201715Z","shell.execute_reply.started":"2022-06-26T01:36:58.191954Z","shell.execute_reply":"2022-06-26T01:36:58.200853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dcm_img_file","metadata":{"id":"dgwe_VOkehnI","outputId":"195c7d17-b518-4e22-fc24-4058e7064bb6","execution":{"iopub.status.busy":"2022-06-26T01:36:58.203366Z","iopub.execute_input":"2022-06-26T01:36:58.203805Z","iopub.status.idle":"2022-06-26T01:36:58.215070Z","shell.execute_reply.started":"2022-06-26T01:36:58.203767Z","shell.execute_reply":"2022-06-26T01:36:58.214012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- The dcm file contains metadata related to file format(version,UIDs, etc.), patient(patientId, Gender, Age, etc.), examination(View position, Body part examined, etc.), pixel data(rows, columns, compression method, etc.)\n- 'Pixel Data' contains the actual image\n- This particular dcm file contains grayscale image(Photometric Interpretation -'MONOCHROME2')\n- We can use the metadata like 'Patient's Sex', 'Patient's Age', 'View Position' to understand the data further.","metadata":{"id":"EBREc0qZvHZy"}},{"cell_type":"markdown","source":"Before that, let's visualize the Pixel Data in the above image.","metadata":{"id":"KeLYfNENxUup"}},{"cell_type":"code","source":"img = dcm_img_file.pixel_array","metadata":{"id":"nYsJIQgsD8fa","execution":{"iopub.status.busy":"2022-06-26T01:36:58.216768Z","iopub.execute_input":"2022-06-26T01:36:58.217128Z","iopub.status.idle":"2022-06-26T01:36:58.236818Z","shell.execute_reply.started":"2022-06-26T01:36:58.217090Z","shell.execute_reply":"2022-06-26T01:36:58.235924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Image shape : {img.shape}')","metadata":{"id":"-SJclT77EFdq","outputId":"d57b4f95-e4ec-47fe-db6d-6dbcd43d3ffe","execution":{"iopub.status.busy":"2022-06-26T01:36:58.238334Z","iopub.execute_input":"2022-06-26T01:36:58.238925Z","iopub.status.idle":"2022-06-26T01:36:58.244288Z","shell.execute_reply.started":"2022-06-26T01:36:58.238889Z","shell.execute_reply":"2022-06-26T01:36:58.243338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"So, it's a grayscale image of resolution 1024x1024.","metadata":{"id":"FBj_x_DfEjtY"}},{"cell_type":"code","source":"plt.figure(figsize = (8,8));\nplt.imshow(img, cmap = plt.cm.gray);\nplt.title(dcm_img_file.PatientID);\nplt.show();","metadata":{"id":"XO4oYbn-EUgB","outputId":"c76a24a0-0a0f-4f00-cb1f-964af43b8837","execution":{"iopub.status.busy":"2022-06-26T01:36:58.245969Z","iopub.execute_input":"2022-06-26T01:36:58.246647Z","iopub.status.idle":"2022-06-26T01:36:58.657950Z","shell.execute_reply.started":"2022-06-26T01:36:58.246605Z","shell.execute_reply":"2022-06-26T01:36:58.656632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's plot x-rays of patients whose:-\n- X-ray class is 'Normal'\n- X-ray class is 'Lung Opacity'\n- X-ray class is 'No Lung Opacity / Not Normal'","metadata":{"id":"Iy55d5WVfqSQ"}},{"cell_type":"code","source":"classes = df['class'].unique()\nfig, ax = plt.subplots(len(classes), 4, figsize = (24, 24))\nfor i, cls in enumerate(classes):\n  for j in range(4):\n    id = df[df['class'] == cls]['patientId'].values[np.random.randint(100)]\n    img_file = pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, id + '.dcm'))\n    img = img_file.pixel_array\n    age = img_file.PatientAge\n    gender = img_file.PatientSex\n    ax[i,j].imshow(img, cmap = plt.cm.gray);\n    ax[i,j].set_title(id + f'\\n({age}/{gender}/{cls})');\nplt.show();","metadata":{"id":"WKEBSyf4j70U","outputId":"8a21d1fa-986f-46ee-92f9-4e2353c13a52","execution":{"iopub.status.busy":"2022-06-26T01:36:58.659019Z","iopub.execute_input":"2022-06-26T01:36:58.659366Z","iopub.status.idle":"2022-06-26T01:37:01.683727Z","shell.execute_reply.started":"2022-06-26T01:36:58.659331Z","shell.execute_reply":"2022-06-26T01:37:01.682354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Let's plot the x-ray of patient having pneumonia with the corresponding patches</b>","metadata":{"id":"uiw2UtI_ts9l"}},{"cell_type":"code","source":"def rsna_get_xray(id):\n  '''\n  Function to return x-ray pixel data\n  Inputs : \n          id - Patient ID\n  '''\n  return pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, id)+'.dcm').pixel_array","metadata":{"id":"XFqLCc8duzOg","execution":{"iopub.status.busy":"2022-06-26T01:37:01.685392Z","iopub.execute_input":"2022-06-26T01:37:01.685936Z","iopub.status.idle":"2022-06-26T01:37:01.690980Z","shell.execute_reply.started":"2022-06-26T01:37:01.685897Z","shell.execute_reply":"2022-06-26T01:37:01.690062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rsna_get_xray_with_bboxes(id):\n  '''\n  Function to return xray with bounding boxes\n  Inputs : \n          id - Patient ID\n  '''\n  img = rsna_get_xray(id)\n  rec = df[df['patientId'] == id]\n  if(rec.shape[0] == 0):\n    return img\n  for i, row in rec.iterrows():\n    if(row['Target'] == 0):\n      continue;\n    img = cv2.rectangle(img, (int(row['x']), int(row['y'])), (int(row['x']) + int(row['width']), int(row['y']) + int(row['height'])), 0, 3)\n  return img","metadata":{"id":"IcAznjAVuWfc","execution":{"iopub.status.busy":"2022-06-26T01:37:01.692534Z","iopub.execute_input":"2022-06-26T01:37:01.692970Z","iopub.status.idle":"2022-06-26T01:37:01.702790Z","shell.execute_reply.started":"2022-06-26T01:37:01.692887Z","shell.execute_reply":"2022-06-26T01:37:01.701941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (8,8))\nid = df.loc[np.random.choice(df[df['Target'] == 1].index)]['patientId']\nplt.imshow(rsna_get_xray_with_bboxes(id), cmap = plt.cm.gray);\nplt.title(id);\nplt.show();","metadata":{"id":"ATpnxpqku7xL","outputId":"6ab8b4eb-c42a-461c-ff81-56f8c0254c35","execution":{"iopub.status.busy":"2022-06-26T01:37:01.704202Z","iopub.execute_input":"2022-06-26T01:37:01.704877Z","iopub.status.idle":"2022-06-26T01:37:02.077194Z","shell.execute_reply.started":"2022-06-26T01:37:01.704842Z","shell.execute_reply":"2022-06-26T01:37:02.076372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Read each dcm file in 'stage_2_train_images' and store metadata in dataframe</b>","metadata":{"id":"AYnbD7Bite75"}},{"cell_type":"code","source":"for filename in os.listdir(TRAIN_IMAGES_BASE_PATH):\n  with pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, filename)) as img:\n    id = img.PatientID\n    age = img.PatientAge\n    gender = img.PatientSex\n    vp = img.ViewPosition\n    ncols = img.Columns\n    nrows = img.Rows\n\n    # Check if patientId exists in dataframe\n    indices = df[df['patientId'] == id].index\n    if(indices.shape[0] != 0):\n      df.loc[indices, 'Age'] = age\n      df.loc[indices, 'Gender'] = gender\n      df.loc[indices, 'View_Position'] = vp\n      df.loc[indices, 'Image_Height'] = nrows\n      df.loc[indices, 'Image_Width'] = ncols","metadata":{"id":"8pJ9U89mw-Yx","outputId":"6d56f39d-f545-4397-a949-ea19938d60b8","execution":{"iopub.status.busy":"2022-06-26T01:37:02.078390Z","iopub.execute_input":"2022-06-26T01:37:02.078886Z","iopub.status.idle":"2022-06-26T01:41:59.008149Z","shell.execute_reply.started":"2022-06-26T01:37:02.078845Z","shell.execute_reply":"2022-06-26T01:41:59.007235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Check how the final dataset looks like","metadata":{"id":"CN6GPwPexMDH"}},{"cell_type":"code","source":"df.info()","metadata":{"id":"iuXC6262ipCX","execution":{"iopub.status.busy":"2022-06-26T01:41:59.009893Z","iopub.execute_input":"2022-06-26T01:41:59.010297Z","iopub.status.idle":"2022-06-26T01:41:59.040740Z","shell.execute_reply.started":"2022-06-26T01:41:59.010256Z","shell.execute_reply":"2022-06-26T01:41:59.039506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.sample(5)","metadata":{"id":"NkoNmNYx3K-J","execution":{"iopub.status.busy":"2022-06-26T01:41:59.042022Z","iopub.execute_input":"2022-06-26T01:41:59.042957Z","iopub.status.idle":"2022-06-26T01:41:59.064323Z","shell.execute_reply.started":"2022-06-26T01:41:59.042911Z","shell.execute_reply":"2022-06-26T01:41:59.063335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- We have added five new columns to dataset - Age, Gender, View Position, Image height and Image Width.\n- Image Height and Image Width have been added just to check if all images are of same resolution. ","metadata":{"id":"uGH9lh2DxrXH"}},{"cell_type":"markdown","source":"Convert the datatypes of some of the columns before we use them further.","metadata":{"id":"Rjg6FGUj7YJg"}},{"cell_type":"code","source":"df['x'] = df['x'].astype('int')\ndf['y'] = df['y'].astype('int')\ndf['width'] = df['width'].astype('int')\ndf['height'] = df['height'].astype('int')\ndf['Image_Width'] = df['Image_Width'].astype('int')\ndf['Image_Height'] = df['Image_Height'].astype('int')\ndf['Age'] = df['Age'].astype('int')","metadata":{"id":"nAS8jN-Q7Nfi","execution":{"iopub.status.busy":"2022-06-26T01:41:59.066226Z","iopub.execute_input":"2022-06-26T01:41:59.066751Z","iopub.status.idle":"2022-06-26T01:41:59.090859Z","shell.execute_reply.started":"2022-06-26T01:41:59.066708Z","shell.execute_reply":"2022-06-26T01:41:59.089979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Regroup the dataframe by 'patientId'","metadata":{"id":"SGm_IIZL2qoC"}},{"cell_type":"code","source":"df_grouped = df.groupby('patientId')","metadata":{"id":"YLPxIjHy2hxR","execution":{"iopub.status.busy":"2022-06-26T01:41:59.092372Z","iopub.execute_input":"2022-06-26T01:41:59.093013Z","iopub.status.idle":"2022-06-26T01:41:59.097879Z","shell.execute_reply.started":"2022-06-26T01:41:59.092973Z","shell.execute_reply":"2022-06-26T01:41:59.097022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Analyzing \"View Position\" Column","metadata":{"id":"MS-TkQXiyV5z"}},{"cell_type":"code","source":"view_positions = df_grouped['View_Position'].aggregate('first')","metadata":{"id":"1DIZKWKf9tYp","execution":{"iopub.status.busy":"2022-06-26T01:41:59.100068Z","iopub.execute_input":"2022-06-26T01:41:59.100878Z","iopub.status.idle":"2022-06-26T01:41:59.150341Z","shell.execute_reply.started":"2022-06-26T01:41:59.100838Z","shell.execute_reply":"2022-06-26T01:41:59.149511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"view_positions.value_counts()","metadata":{"id":"ju5m1Fjf2x9h","outputId":"9638e5d8-5f0e-43e3-fc82-3cf12f6e1d76","execution":{"iopub.status.busy":"2022-06-26T01:41:59.151793Z","iopub.execute_input":"2022-06-26T01:41:59.152364Z","iopub.status.idle":"2022-06-26T01:41:59.167082Z","shell.execute_reply.started":"2022-06-26T01:41:59.152326Z","shell.execute_reply":"2022-06-26T01:41:59.166298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are two different View Positions in dataset :-\n- PA (Posterior-Anterior)\n- AP (Anterior-Posterior)  \n\nPA radiographs are taken while the patient faces away from the X-ray tube. X-rays enter from their Posterior and comes out of their Anterior.  \n\nAP radiographs are taken with the patient facing the X-ray tube, so that x-ray beams enter their Anterior and exits from Posterior.\n\n![cxr_aeaac.jpg](data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4Sd2RXhpZgAATU0AKgAAAAgACQALAAIAAAAmAAAIhgESAAMAAAABAAEAAAEaAAUAAAABAAAIrAEbAAUAAAABAAAItAEoAAMAAAABAAIAAAExAAIAAAAmAAAIvAEyAAIAAAAUAAAI4odpAAQAAAABAAAI9uocAAcAAAgMAAAAegAAEToc6gAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFdpbmRvd3MgUGhvdG8gRWRpdG9yIDEwLjAuMTAwMTEuMTYzODQAAAr8gAAAJxAACvyAAAAnEFdpbmRvd3MgUGhvdG8gRWRpdG9yIDEwLjAuMTAwMTEuMTYzODQAMjAyMjowNjowMyAxNTowNTo0NAAABKABAAMAAAABAAEAAKACAAQAAAABAAADhKADAAQAAAABAAAAluocAAcAAAgMAAAJLAAAAAAc6gAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAwADAAAAAQAGAAABGgAFAAAAAQAAEYgBGwAFAAAAAQAAEZABKAADAAAAAQACAAACAQAEAAAAAQAA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gcboGg7+zk/UUuq6PdG8TUNPdvtIePOCvyqquDgMMNnfyCR6g8cgFnw1ptzpWjLBeS+bcPNNPI2QeZJGfGQADjdjoK16ACigAooAKa8aOVLorbTlcjOD60AJ5Mfm+b5a+Zjbvxzj0zQIYg7uIkDOMM20Zb6+tABJDFMAJY0cA5AZc4PrQ8MUjIzxozIcqSMlT7elAD6KACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigAooAKKACigD/2QD/7Q+yUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAccAgAAAgACADhCSU0EJQAAAAAAEEYM8okmuFbasJwBobCnkHc4QklNA+0AAAAAABAASAAAAAEAAgBIAAAAAQACOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAB4OEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAI4QklNA/UAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA/gAAAAAAHAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAOEJJTQQAAAAAAAACAAE4QklNBAIAAAAAAAQAAAAAOEJJTQQwAAAAAAACAQE4QklNBC0AAAAAAAYAAQAAACo4QklNBAgAAAAAAB8AAAABAAACQAAAAkAAAAADAAAJJAEAAAM8AQAAKSgAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA0cAAAAGAAAAAAAAAAAAAACWAAADhAAAAAkAYwB4AHIAXwBhAGUAYQBhAGMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAA4QAAACWAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEA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aHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPg0KCQkJPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPg0KCQkJPHhhcDpDcmVhdG9yVG9vbD5XaW5kb3dzIFBob3RvIEVkaXRvciAxMC4wLjEwMDExLjE2Mzg0PC94YXA6Q3JlYXRvclRvb2w+DQoJCQk8eGFwOkNyZWF0ZURhdGU+MjAwOS0xMC0yMFQxMToyMjoxMyswMTowMDwveGFwOkNyZWF0ZURhdGU+DQoJCQk8eGFwOk1vZGlmeURhdGU+MjAwOS0xMC0yMFQxMToyMzo0OCswMTowMDwveGFwOk1vZGlmeURhdGU+DQoJCQk8eGFwOk1ldGFkYXRhRGF0ZT4yMDA5LTEwLTIwVDExOjIzOjQ4KzAxOjAwPC94YXA6TWV0YWRhdGFEYXRlPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eGFwTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIj4NCgkJCTx4YXBNTTpEb2N1bWVudElEPnV1aWQ6NjczNTc0REI1RkJEREUxMUI1M0JCOTUzQTU4OTNCNjU8L3hhcE1NOkRvY3VtZW50SUQ+DQoJCQk8eGFwTU06SW5zdGFuY2VJRD51dWlkOjZEMzU3NERCNUZCRERFMTFCNTNCQjk1M0E1ODkzQjY1PC94YXBNTTpJbnN0YW5jZUlEPg0KCQkJPHhhcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4NCgkJCQk8c3RSZWY6aW5zdGFuY2VJRD51dWlkOkE2NjlBNjg4NUZCRERFMTFCNTNCQjk1M0E1ODkzQjY1PC9zdFJlZjppbnN0YW5jZUlEPg0KCQkJCTxzdFJlZjpkb2N1bWVudElEPnV1aWQ6MDY2NDcwNUY1RkJEREUxMUI1M0JCOTUzQTU4OTNCNjU8L3N0UmVmOmRvY3VtZW50SUQ+DQoJCQk8L3hhcE1NOkRlcml2ZWRGcm9tPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPg0KCQkJPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPg0KCQkJPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPg0KCQkJPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4NCgkJCTx0aWZmOk5hdGl2ZURpZ2VzdD4yNTYsMjU3LDI1OCwyNTksMjYyLDI3NCwyNzcsMjg0LDUzMCw1MzEsMjgyLDI4MywyOTYsMzAxLDMxOCwzMTksNTI5LDUzMiwzMDYsMjcwLDI3MSwyNzIsMzA1LDMxNSwzMzQzMjtDOURFOTYwQUUyMUFDQzM0RUNDRDQzQ0I4NDA3REM2MDwvdGlmZjpOYXRpdmVEaWdlc3Q+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+DQoJCQk8ZXhpZjpQaXhlbFhEaW1lbnNpb24+OTAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4NCgkJCTxleGlmOlBpeGVsWURpbWVuc2lvbj4xNTA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPg0KCQkJPGV4aWY6Q29sb3JTcGFjZT4tMTwvZXhpZjpDb2xvclNwYWNlPg0KCQkJPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtEQUY5NUFFMTk5NDE5MjRGREZENkIwQjVDMTA3NDVDRTwvZXhpZjpOYXRpdmVEaWdlc3Q+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPg0KCQkJPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4NCgkJCTxwaG90b3Nob3A6SGlzdG9yeS8+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCTwvcmRmOlJERj4NCjwveDp4bXBtZXRhPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0ndyc/Pv/bAEMAAwICAwICAwMDAwQDAwQFCAUFBAQFCgcHBggMCgwMCwoLCw0OEhANDhEOCwsQFhARExQVFRUMDxcYFhQYEhQVFP/bAEMBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFP/AABEIAJYBkAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP1TooooAKKKKACiiigAooooAKKKKACi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XfmmeF/2e7m8+BPjz4e+KriO3XxLq+uXS3OnSF2hiu72aeGQEgfvFEiMRjG4Umm6l+0Fb6NbeHJvD/g99ViVYH8ZtqcptXUAAziwEYk8wjny/MC5/jxQBD8Sv2jLzSfiPP4E8Kt4XtNX06zhvdX1HxlrAsrW084MYYERQXmlZVLHbhUXblssBXUfA344QfFk+IdLuk0238T+HJ44NSj0fUVv7KRZF3wzwTKBujdQ3DBWVlZSOMnifH3wU1jR/i1rPjvQ/Bfhf4i2viG0totU0fXTHb3EF1AhjS4tppIpF2NHhXjOPuKQc5B7z4H+Bdc8JafrF74g0vw1oV9qd0JYtI8L2iR29jAqgLE0wRGnfO5mdlAy2FAAoA9RooooAKKKKACiiigAooooAKKKKACiiigAooooAz9b0PT/ABNpN3peq2cOo6ddxmKe1uUDxyqeqsp4IquvhfSBNq0g0y1L6vj+0CYVP2vEYjHmgj58IoXntxWxRQBwPhv4F+APB9lq1npHhPTLK21a3a0vYxDvE9uQQYW3Z/d4Yjyx8vPSuqk8N6XLc6XcPYQNPpYYWMhjBa2DJsbYf4cr8vHatSigDP0XQ7Dw5pdvpulWcOn2FuCsVtboERBkkgAcDk5rQoooAKKKKACo2kRDhmAPoTUlfO3xe/YH+DPxz8d33jHxj4fvdQ1+9SOOaeHVbmBSI0CJhEcKMKo6CgDhvAbB/wDgqN8SipBH/CvrLkc/8vENfVXiiTWo/DupP4djs59dWBjZR6izLbvLj5VkZfmCk9xXkfwJ/Yx+FP7NviS/1/wFod1pep31obGeWfUZ7gNEXV9u2R2AO5F5AzXulAHyJ4u+EXjf4iR/FfVdL8DP4Fk8T+FG0260W41S3k/tfViw2XWInaNBGgaPzWKvIHXco2CvY9J8C61afF74g67LbIumav4c0nT7OUSgs80DXxlUrnKgefFyeufavWKKAPkG8/Z88czfC/w9oq6XbnUbT4S6t4UmjN3HgajOLLyot2cFT5MmX+6Me9eveLvh3q+q6l8HGtrZUsvDt5M+p7JlQwRNpN1bAoP4iJJUAx9egr2CigD4R8XeMvEGg/sW6z4I0nTdA1nRYNDl8Paf4sh1WI2t/HtMEUa2oHni9fhDEUwJcnfivt/Q7eS00XT4JV2SxW8aOvoQoBH51gj4TeCV8Vf8JOvhDQV8SbzJ/a402EXW89W83bu3e+c11tABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH/9k=)![cxr_aeaab.jpg](data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4SUKRXhpZgAATU0AKgAAAAgACQALAAIAAAAmAAAIhgESAAMAAAABAAEAAAEaAAUAAAABAAAIrAEbAAUAAAABAAAItAEoAAMAAAABAAIAAAExAAIAAAAmAAAIvAEyAAIAAAAUAAAI4odpAAQAAAABAAAI9uocAAcAAAgMAAAAegAAEToc6gAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFdpbmRvd3MgUGhvdG8gRWRpdG9yIDEwLjAuMTAwMTEuMTYzODQAAAr8gAAAJxAACvyAAAAnEFdpbmRvd3MgUGhvdG8gRWRpdG9yIDEwLjAuMTAwMTEuMTYzODQAMjAyMjowNjowMyAxNTowNToyMwAABKABAAMAAAABAAEAAKACAAQAAAABAAADhKADAAQAAAABAAAAluocAAcAAAgMAAAJLAAAAAAc6gAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAwADAAAAAQAGAAABGgAFAAAAAQAAEYgBGwAFAAAAAQAAEZABKAADAAAAAQACAAACAQAEAAAAAQAA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hJavItmssqhkXyNiGQIxVyGAUE5OAM98gD7fStUutSjBTV7PSzJGXjn1DdJxHOG+ZXZgCxi6N29M1FNpmu3Ftbx3VvfTXg+yv5y3aiFQnlmQMm4ZbcrnO09R83YACjTtesdJguPPuVuQjrc7py6pGIDjaoJAO8DkAkZPatDw5O9xbas6C7W0GFhW5ufPI+T5sOGYHk9mb6joAC14E/5J94b/AOwXbf8Aopa6CgAooAKwvE6aj9khm0t5BcQu7hEXcHPlPtDDjI3Y478UAUhda95zQK8jSeaIyWtPkRPMVRIG4DEpliB09sc3tIk1f7WyX5LxlZMN5QTaUkKr07suG/lgcUAblFABRQAUUAFFABRQAUUAFFABRQAUUAFFABRQAVFdcWk3+438qAOa8CalY/8ACC+G4Pttv539m2y+X5q7s+WvGM5zXVUAFFABWH4mvb/T7WG5sdrGNnZ4iCfMAichcjoMgc/SgCl/wkGoiZoBFaPceb5JiG8NH+9VBI3XCsCWHtjk8kXtIvtQvL+dbpY0hjQptVCMussibgT2IUHHbPWgDbooAKKACigAooAKKACigAooAKKACigAooAKKACkIDAgjIPUGgDJg8K+HbaeOe30HS4Zo2DJJHZxqykdCCBkGtegAooAKTGaADAowKAFooA//9kA/+0Q8lBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAHHAIAAAIAAgA4QklNBCUAAAAAABBGDPKJJrhW2rCcAaGwp5B3OEJJTQPtAAAAAAAQAEgAAAABAAIASAAAAAEAAjhCSU0EJgAAAAAADgAAAAAAAAAAAAA/gAAAOEJJTQQNAAAAAAAEAAAAeDhCSU0EGQAAAAAABAAAAB44QklNA/MAAAAAAAkAAAAAAAAAAAEAOEJJTQQKAAAAAAABAAA4QklNJxAAAAAAAAoAAQAAAAAAAAACOEJJTQP1AAAAAABIAC9mZgABAGxmZgAGAAAAAAABAC9mZgABAKGZmgAGAAAAAAABADIAAAABAFoAAAAGAAAAAAABADUAAAABAC0AAAAGAAAAAAABOEJJTQP4AAAAAABwAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAADhCSU0EAAAAAAAAAgABOEJJTQQCAAAAAAAEAAAAADhCSU0EMAAAAAAAAgEBOEJJTQQtAAAAAAAGAAEAAAAmOEJJTQQIAAAAAAAkAAAAAQAAAkAAAAJAAAAABAAACSQBAAADPAEAACpUAAAAHbgAOEJJTQQeAAAAAAAEAAAAADhCSU0EGgAAAAADRwAAAAYAAAAAAAAAAAAAAJYAAAOEAAAACQBjAHgAcgBfAGEAZQBhAGEAYgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAADhAAAAJYAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAG51bGwAAAACAAAABmJvdW5kc09iamMAAAABAAAAAAAAUmN0MQAAAAQAAAAAVG9wIGxvbmcAAAAAAAAAAExlZnRsb25nAAAAAAAAAABCdG9tbG9uZwAAAJYAAAAAUmdodGxvbmcAAAOEAAAABnNsaWNlc1ZsTHMAAAABT2JqYwAAAAEAAAAAAAVzbGljZQAAABIAAAAHc2xpY2VJRGxvbmcAAAAAAAAAB2dyb3VwSURsb25nAAAAAAAAAAZvcmlnaW5lbnVtAAAADEVTbGljZU9yaWdpbgAAAA1hdXRvR2VuZXJhdGVkAAAAAFR5cGVlbnVtAAAACkVTbGljZVR5cGUAAAAASW1nIAAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAACWAAAAAFJnaHRsb25nAAADhAAAAAN1cmxURVhUAAAAAQAAAAAAAG51bGxURVhUAAAAAQAAAAAAAE1zZ2VURVhUAAAAAQAAAAAABmFsdFRhZ1RFWFQAAAABAAAAAAAOY2VsbFRleHRJc0hUTUxib29sAQAAAAhjZWxsVGV4dFRFWFQAAAABAAAAAAAJaG9yekFsaWduZW51bQAAAA9FU2xpY2VIb3J6QWxpZ24AAAAHZGVmYXVsdAAAAAl2ZXJ0QWxpZ25lbnVtAAAAD0VTbGljZVZlcnRBbGlnbgAAAAdkZWZhdWx0AAAAC2JnQ29sb3JUeXBlZW51bQAAABFFU2xpY2VCR0NvbG9yVHlwZQAAAABOb25lAAAACXRvcE91dHNldGxvbmcAAAAAAAAACmxlZnRPdXRzZXRsb25nAAAAAAAAAAxib3R0b21PdXRzZXRsb25nAAAAAAAAAAtyaWdodE91dHNldGxvbmcAAAAAADhCSU0EKAAAAAAADAAAAAE/8AAAAAAAADhCSU0EEQAAAAAAAQEAOEJJTQQUAAAAAAAEAAAAJzhCSU0EDAAAAAAIiwAAAAEAAACgAAAAGwAAAeAAADKgAAAIbwAYAAH/2P/gABBKRklGAAECAABIAEgAAP/tAAxBZG9iZV9DTQAC/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBELCgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsNDg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAGwCgAwEiAAIRAQMRAf/dAAQACv/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYHCAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQhEjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXiZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIEBAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKygwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dXZ3eHl6e3x//aAAwDAQACEQMRAD8A9VTHhZvVeoZeI4fZ2CzRp9P2hzgXO9VzH2201/oa2/zf+EsfUz9F/OKWLnZ1rHE43qtDnNZdW5rWvAfZXu2WO9vsYx/0rPppKa9fUMthHqZeE6sGHOc4g6Crf+lHp0uduu/0f+jRsTNyDbsuysS1tbS6wVEmwga79m72/mfmohY3aGuwq2Bs7QW7wJjdDamO/dSZtr1YK6dSf5h7dT9L3SxJTz3Uf8Z31dox25HT7m9Q2EOvpAsqs9GR6tuP61Ho221N/Sehbbj+p/plv05eXnY9eb022i3Dymttx32Msadjmtc0kS13vd+8yrYh9RwOm9WqZj9RvF9DLG2nH3Btb3MO6tuRUD+sVMf7/Qu/Q/6St6vNpD9fWe8eTgP/AD0GJKazreq1ljbXY7Ta4Ma9rXkNdBfLmuezd9D02+/6djFB+ZnjEGabMXHx3NbZNxcA1rmt/nLdzG/TT9ZxKHdJzA9psaaXy17nPGgn6L3OUOu04tfT7LXVsDWkOsdtH0P8L/4HvSU28C+2+kWvtouY/Wp+OS5rmx9Ldudu937qtLgfqn0ezIsrdnU2U4/UMS9/ptccd9bTlMvx6a3YzqciltuN6Tnsrcz+b/TLV+qlnVG/WD6xYOXb6mJh24zMNhe+wtYaZZ773WWbnY/2b1nbv0mT61qSnqUx4Wb1XqGXiOH2dgs0afT9oc4FzvVcx9ttNf6Gtv8AN/4Sx9TP0X84pYudnWscTjeq0Oc1l1bmta8B9le7ZY72+xjH/Ss+mkpr19Qy2Eepl4TqwYc5ziDoKt/6UenS5267/R/6NGxM3INuy7KxLW1tLrBUSbCBrv2bvb+Z+aiFjdoa7CrYGztBbvAmN0NqY791Jm2vVgrp1J/mHt1P0vdLElPPdR/xnfV2jHbkdPub1DYQ6+kCyqz0ZHq24/rUejbbU39J6FtuP6n+mW/Tl5edj15vTbaLcPKa23HfYyxp2Oa1zSRLXe937zKtiH1HA6b1apmP1G8X0MsbacfcG1vcw7q25FQP6xUx/v8AQu/Q/wCkrerzaQ/X1nvHk4D/AM9BiSms63qtZY212O02uDGva15DXQXy5rns3fQ9Nvv+nYxQfmZ4xBmmzFx8dzW2TcXANa5rf5y3cxv00/WcSh3ScwPabGml8te5zxoJ+i9zlDrtOLX0+y11bA1pDrHbR9D/AAv/AIHvSU28C+2+kWvtouY/Wp+OS5rmx9Ldudu937qtLgfqn0ezIsrdnU2U4/UMS9/ptccd9bTlMvx6a3YzqciltuN6Tnsrcz+b/TLV+qlnVG/WD6xYOXb6mJh24zMNhe+wtYaZZ773WWbnY/2b1nbv0mT61qSn/9D0XOaftLXejkP9gaX0P2gAvD3aBzHb2+nu/wCK9Sv/AIK1dOddURS6nIizc91l72v2GGfo9wd+dP8Agt7FoJJKUkkkkpYgHQqlfubcWt6eL2aRYCwanys2/RV5JJTh573OwMpj8GzGDqrtrw4bYaxzmuf6L/ZvV/O6XVm4tmM622ttoguY+XCf3fV9Vv8A0VPqmz9m5W/bs9F+7fu2xtM7vR/Tf9tfpP3EbH2ehX6e/ZtG31N++I09T1/02/8Ae9X9IkprZbHU47WY3qMcTtDqtjniGvIc77T/ADvH/Gf2N6hg4TmXvzNxZZeZyGOrpa95YHU1+vbjD9JsZs2fpPzE/WI+z1z9mj1P+1c7foWfzW3/AA3/AKK9VF6b/Q2fzHLv6N/NfSd9D/v/APLSUhzmn7S13o5D/YGl9D9oALw92gcx29vp7v8AivUr/wCCtXTnXVEUupyIs3PdZe9r9hhn6PcHfnT/AILexaCSSlJJJJKWIB0KpX7m3Freni9mkWAsGp8rNv0VeSSU4ee9zsDKY/Bsxg6q7a8OG2Gsc5rn+i/2b1fzul1ZuLZjOttrbaILmPlwn931fVb/ANFT6ps/ZuVv27PRfu37tsbTO70f03/bX6T9xGx9noV+nv2bRt9TfviNPU9f9Nv/AHvV/SJKa2Wx1OO1mN6jHE7Q6rY54hryHO+0/wA7x/xn9jeoYOE5l78zcWWXmchjq6WveWB1Nfr24w/SbGbNn6T8xP1iPs9c/Zo9T/tXO36Fn81t/wAN/wCivVRem/0Nn8xy7+jfzX0nfQ/7/wDy0lP/2QA4QklNBCEAAAAAAFUAAAABAQAAAA8AQQBkAG8AYgBlACAAUABoAG8AdABvAHMAaABvAHAAAAATAEEAZABvAGIAZQAgAFAAaABvAHQAbwBzAGgAbwBwACAAQwBTADIAAAABADhCSU0PoAAAAAAA+G1hbmlJUkZSAAAA7DhCSU1BbkRzAAAAzAAAABAAAAABAAAAAAAAbnVsbAAAAAMAAAAAQUZTdGxvbmcAAAAAAAAAAEZySW5WbExzAAAAAU9iamMAAAABAAAAAAAAbnVsbAAAAAEAAAAARnJJRGxvbmdWJrKtAAAAAEZTdHNWbExzAAAAAU9iamMAAAABAAAAAAAAbnVsbAAAAAQAAAAARnNJRGxvbmcAAAAAAAAAAEFGcm1sb25nAAAAAAAAAABGc0ZyVmxMcwAAAAFsb25nViayrQAAAABMQ250bG9uZwAAAAAAADhCSU1Sb2xsAAAACAAAAAAAAAAAOEJJTQ+hAAAAAAAcbWZyaQAAAAIAAAAQAAAAAQAAAAAAAAABAAAAADhCSU0EAQAAAAABBAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAACAGaS+wBwNnkAZpL7AHA2eQBmkvsAcDZ5AAIAZpL7AHMtjABmkvsAcy2MAGaS+wBzLYwAAgBq4X8Acy2MAGrhfwBzLYwAauF/AHMtjAACAGKPXgB13gEAYo9eAHXeAQBij14Add4BAAIAWj04AHMtjABaPTgAcy2MAFo9OABzLYwAAgBei8AAcy2MAF6LwABzLYwAXovAAHMtjAACAF6LwABwNnkAXovAAHA2eQBei8AAcDZ5OEJJTQQGAAAAAAAHAAMAAAABAQD/4TpQaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pg0KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iMy4xLjEtMTEyIj4NCgk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPg0KCQkJPGRjOmZvcm1hdD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4YXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPg0KCQkJPHhhcDpDcmVhdG9yVG9vbD5XaW5kb3dzIFBob3RvIEVkaXRvciAxMC4wLjEwMDExLjE2Mzg0PC94YXA6Q3JlYXRvclRvb2w+DQoJCQk8eGFwOkNyZWF0ZURhdGU+MjAwOS0xMC0yMFQxMTowMjozMSswMTowMDwveGFwOkNyZWF0ZURhdGU+DQoJCQk8eGFwOk1vZGlmeURhdGU+MjAwOS0xMC0yMFQxMTowMzo0NiswMTowMDwveGFwOk1vZGlmeURhdGU+DQoJCQk8eGFwOk1ldGFkYXRhRGF0ZT4yMDA5LTEwLTIwVDExOjAzOjQ2KzAxOjAwPC94YXA6TWV0YWRhdGFEYXRlPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eGFwTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIj4NCgkJCTx4YXBNTTpEb2N1bWVudElEPnV1aWQ6QUE2OUE2ODg1RkJEREUxMUI1M0JCOTUzQTU4OTNCNjU8L3hhcE1NOkRvY3VtZW50SUQ+DQoJCQk8eGFwTU06SW5zdGFuY2VJRD51dWlkOkIwNjlBNjg4NUZCRERFMTFCNTNCQjk1M0E1ODkzQjY1PC94YXBNTTpJbnN0YW5jZUlEPg0KCQkJPHhhcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4NCgkJCQk8c3RSZWY6aW5zdGFuY2VJRD51dWlkOjA0NjQ3MDVGNUZCRERFMTFCNTNCQjk1M0E1ODkzQjY1PC9zdFJlZjppbnN0YW5jZUlEPg0KCQkJCTxzdFJlZjpkb2N1bWVudElEPnV1aWQ6MDM2NDcwNUY1RkJEREUxMUI1M0JCOTUzQTU4OTNCNjU8L3N0UmVmOmRvY3VtZW50SUQ+DQoJCQk8L3hhcE1NOkRlcml2ZWRGcm9tPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPg0KCQkJPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPg0KCQkJPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPg0KCQkJPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4NCgkJCTx0aWZmOk5hdGl2ZURpZ2VzdD4yNTYsMjU3LDI1OCwyNTksMjYyLDI3NCwyNzcsMjg0LDUzMCw1MzEsMjgyLDI4MywyOTYsMzAxLDMxOCwzMTksNTI5LDUzMiwzMDYsMjcwLDI3MSwyNzIsMzA1LDMxNSwzMzQzMjsxNDg5MDk3OEIyRTRCMjU3NUE0MzNFNjAxMDY1NDk1MzwvdGlmZjpOYXRpdmVEaWdlc3Q+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+DQoJCQk8ZXhpZjpQaXhlbFhEaW1lbnNpb24+OTAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4NCgkJCTxleGlmOlBpeGVsWURpbWVuc2lvbj4xNTA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPg0KCQkJPGV4aWY6Q29sb3JTcGFjZT4tMTwvZXhpZjpDb2xvclNwYWNlPg0KCQkJPGV4aWY6TmF0aXZlRGlnZXN0PjM2ODY0LDQwOTYwLDQwOTYxLDM3MTIxLDM3MTIyLDQwOTYyLDQwOTYzLDM3NTEwLDQwOTY0LDM2ODY3LDM2ODY4LDMzNDM0LDMzNDM3LDM0ODUwLDM0ODUyLDM0ODU1LDM0ODU2LDM3Mzc3LDM3Mzc4LDM3Mzc5LDM3MzgwLDM3MzgxLDM3MzgyLDM3MzgzLDM3Mzg0LDM3Mzg1LDM3Mzg2LDM3Mzk2LDQxNDgzLDQxNDg0LDQxNDg2LDQxNDg3LDQxNDg4LDQxNDkyLDQxNDkzLDQxNDk1LDQxNzI4LDQxNzI5LDQxNzMwLDQxOTg1LDQxOTg2LDQxOTg3LDQxOTg4LDQxOTg5LDQxOTkwLDQxOTkxLDQxOTkyLDQxOTkzLDQxOTk0LDQxOTk1LDQxOTk2LDQyMDE2LDAsMiw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwyMCwyMiwyMywyNCwyNSwyNiwyNywyOCwzMDtEQUY5NUFFMTk5NDE5MjRGREZENkIwQjVDMTA3NDVDRTwvZXhpZjpOYXRpdmVEaWdlc3Q+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPg0KCQkJPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4NCgkJCTxwaG90b3Nob3A6SGlzdG9yeS8+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCTwvcmRmOlJERj4NCjwveDp4bXBtZXRhPg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0ndyc/Pv/bAEMAAwICAwICAwMDAwQDAwQFCAUFBAQF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)\n\nReferences :-\n- https://chiro.org/radiology/ABSTRACTS/procedures.pdf\n- https://www.radiologymasterclass.co.uk/tutorials/chest/chest_quality/chest_xray_quality_projection","metadata":{"id":"2NS3xIjLx4-Z"}},{"cell_type":"code","source":"countplot_with_percentage(view_positions, 'View Position')","metadata":{"id":"JmpRcWcN7zq5","outputId":"01fc17ae-180c-42cc-fa09-6540366eba7e","execution":{"iopub.status.busy":"2022-06-26T01:41:59.169617Z","iopub.execute_input":"2022-06-26T01:41:59.170048Z","iopub.status.idle":"2022-06-26T01:41:59.383995Z","shell.execute_reply.started":"2022-06-26T01:41:59.170018Z","shell.execute_reply":"2022-06-26T01:41:59.383152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- PA position X-ray counts are slightly higher than the AP position X-rays in dataset.","metadata":{"id":"r5IjBNQU-G6v"}},{"cell_type":"code","source":"target = df_grouped['Target'].aggregate('first')","metadata":{"id":"v3K2Qz6y4V0C","execution":{"iopub.status.busy":"2022-06-26T01:41:59.385236Z","iopub.execute_input":"2022-06-26T01:41:59.386068Z","iopub.status.idle":"2022-06-26T01:41:59.392734Z","shell.execute_reply.started":"2022-06-26T01:41:59.386029Z","shell.execute_reply":"2022-06-26T01:41:59.391918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (8,8));\nsns.countplot(x = view_positions, hue = target);\nplt.title('Target by View Position');\nplt.show();","metadata":{"id":"EPabvPAg4RwP","outputId":"6a14cb30-bba8-4f9a-bec2-476b5a61e549","execution":{"iopub.status.busy":"2022-06-26T01:41:59.394296Z","iopub.execute_input":"2022-06-26T01:41:59.395171Z","iopub.status.idle":"2022-06-26T01:41:59.633358Z","shell.execute_reply.started":"2022-06-26T01:41:59.395134Z","shell.execute_reply":"2022-06-26T01:41:59.632396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- X-rays taken in AP view have more pneumonia cases than those taken in PA position.","metadata":{"id":"iMpcbU1k6O5b"}},{"cell_type":"markdown","source":"Analyzing \"Gender\" Column","metadata":{"id":"m6CGsrKL-n45"}},{"cell_type":"code","source":"gender = df_grouped['Gender'].aggregate('first')","metadata":{"id":"bzv8mmup-pTl","execution":{"iopub.status.busy":"2022-06-26T01:41:59.634799Z","iopub.execute_input":"2022-06-26T01:41:59.635162Z","iopub.status.idle":"2022-06-26T01:41:59.645247Z","shell.execute_reply.started":"2022-06-26T01:41:59.635125Z","shell.execute_reply":"2022-06-26T01:41:59.644355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gender.value_counts()","metadata":{"id":"2hkedPRK-vUW","outputId":"51f5112f-f52a-42d8-afea-2b83af2e4cd4","execution":{"iopub.status.busy":"2022-06-26T01:41:59.646986Z","iopub.execute_input":"2022-06-26T01:41:59.647704Z","iopub.status.idle":"2022-06-26T01:41:59.659029Z","shell.execute_reply.started":"2022-06-26T01:41:59.647660Z","shell.execute_reply":"2022-06-26T01:41:59.658227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"countplot_with_percentage(gender, 'Gender')","metadata":{"id":"aSN28SKb-4vh","outputId":"9297a665-acad-46c6-d358-a38632064e21","execution":{"iopub.status.busy":"2022-06-26T01:41:59.660567Z","iopub.execute_input":"2022-06-26T01:41:59.661186Z","iopub.status.idle":"2022-06-26T01:41:59.868118Z","shell.execute_reply.started":"2022-06-26T01:41:59.661146Z","shell.execute_reply":"2022-06-26T01:41:59.867281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- 57% of the patients are Male in dataset.","metadata":{"id":"7SeJ_3t6_L34"}},{"cell_type":"markdown","source":"Target distribution by Gender","metadata":{"id":"0zvRyWrQAuwn"}},{"cell_type":"code","source":"target = df_grouped['Target'].aggregate('first')","metadata":{"id":"9EZQio2BAnUZ","execution":{"iopub.status.busy":"2022-06-26T01:41:59.869448Z","iopub.execute_input":"2022-06-26T01:41:59.869858Z","iopub.status.idle":"2022-06-26T01:41:59.876652Z","shell.execute_reply.started":"2022-06-26T01:41:59.869817Z","shell.execute_reply":"2022-06-26T01:41:59.875684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (8,8));\nsns.countplot(x = target, hue = gender);\nplt.title('Gender Distribution by Target');\nplt.show();","metadata":{"id":"iK6uqz5RA1pZ","outputId":"3bcc9498-f408-4a14-e133-e443910dbb42","execution":{"iopub.status.busy":"2022-06-26T01:41:59.878273Z","iopub.execute_input":"2022-06-26T01:41:59.878743Z","iopub.status.idle":"2022-06-26T01:42:00.106137Z","shell.execute_reply.started":"2022-06-26T01:41:59.878703Z","shell.execute_reply":"2022-06-26T01:42:00.105296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Analyzing \"Age\" column","metadata":{"id":"ZiylkZ5A-XBA"}},{"cell_type":"code","source":"age = df_grouped['Age'].aggregate('first')","metadata":{"id":"iYOMymGQi3sG","execution":{"iopub.status.busy":"2022-06-26T01:42:00.107612Z","iopub.execute_input":"2022-06-26T01:42:00.108180Z","iopub.status.idle":"2022-06-26T01:42:00.113611Z","shell.execute_reply.started":"2022-06-26T01:42:00.108141Z","shell.execute_reply":"2022-06-26T01:42:00.112724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"age.describe()","metadata":{"id":"shv1NAFY-eSn","outputId":"b7512ffc-ba57-4654-baf1-50d447bfed73","execution":{"iopub.status.busy":"2022-06-26T01:42:00.115036Z","iopub.execute_input":"2022-06-26T01:42:00.115762Z","iopub.status.idle":"2022-06-26T01:42:00.132079Z","shell.execute_reply.started":"2022-06-26T01:42:00.115727Z","shell.execute_reply":"2022-06-26T01:42:00.130813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (6,8));\nsns.boxplot(y = age);\nplt.title('Boxplot - Age');\nplt.show();","metadata":{"id":"5YX3JFluGbGJ","outputId":"8c034b37-05ec-4f2a-a19b-c5b47f66a5e8","execution":{"iopub.status.busy":"2022-06-26T01:42:00.133849Z","iopub.execute_input":"2022-06-26T01:42:00.134668Z","iopub.status.idle":"2022-06-26T01:42:00.306223Z","shell.execute_reply.started":"2022-06-26T01:42:00.134613Z","shell.execute_reply":"2022-06-26T01:42:00.305330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (20,6));\nsns.histplot(age, kde = True);\nplt.title('Age Distribution');\nplt.show();","metadata":{"id":"OKQt8T3f_b0n","outputId":"fee09f86-6432-4178-bfe4-7b20b1f5a790","execution":{"iopub.status.busy":"2022-06-26T01:42:00.307854Z","iopub.execute_input":"2022-06-26T01:42:00.308611Z","iopub.status.idle":"2022-06-26T01:42:01.132915Z","shell.execute_reply.started":"2022-06-26T01:42:00.308564Z","shell.execute_reply":"2022-06-26T01:42:01.132012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Mean age is 49 years in dataset.\n- 75% of the patients are less than 59 years.\n- There are certain patients whose age is above 140 years. Most likely these are incorrect records in the dataset.","metadata":{"id":"zJBu-n0eLqqu"}},{"cell_type":"code","source":"fig = plt.figure(figsize = (8, 6));\nsns.boxplot(y = age, x = target);\nplt.title('Age Distribution by Target');\nplt.show();","metadata":{"id":"fu7dhprCBRBB","outputId":"b87d758d-e40a-4477-8ec5-2ec696ecf50b","execution":{"iopub.status.busy":"2022-06-26T01:42:01.134224Z","iopub.execute_input":"2022-06-26T01:42:01.135765Z","iopub.status.idle":"2022-06-26T01:42:01.330153Z","shell.execute_reply.started":"2022-06-26T01:42:01.135724Z","shell.execute_reply":"2022-06-26T01:42:01.329338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Age distribution is similar for normal patients and patients with pneumonia. \n","metadata":{"id":"99bBa5iK_Zmm"}},{"cell_type":"markdown","source":"Check if all images are of same resolution","metadata":{"id":"1R8HF-Cw6jzF"}},{"cell_type":"code","source":"print('Number of unique values in Image Height : ',df['Image_Height'].unique())\nprint('Number of unique values in Image Width : ',df['Image_Width'].unique())","metadata":{"id":"xs9hDUqc6qbH","outputId":"bd7154e0-9f89-4bf3-fb64-2ed12690b35c","execution":{"iopub.status.busy":"2022-06-26T01:42:01.331410Z","iopub.execute_input":"2022-06-26T01:42:01.332780Z","iopub.status.idle":"2022-06-26T01:42:01.339682Z","shell.execute_reply.started":"2022-06-26T01:42:01.332738Z","shell.execute_reply":"2022-06-26T01:42:01.338818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"All Images are of same resolution.","metadata":{"id":"u0NtW3cwj8CO"}},{"cell_type":"markdown","source":"### Data Prepration and pre-processing","metadata":{"id":"FCJARW7Z7UD9"}},{"cell_type":"markdown","source":"To be able to use data in model building, we will first split the data into train, test and validation. Then we would store the images in png format so that we can use images in model building via ImageGenerators( and apply augmentation as well).","metadata":{"id":"gRIBHlD17d9A"}},{"cell_type":"markdown","source":"<b>Split data into train, test and validation sets</b>","metadata":{"id":"EeVgUbQQ8aQl"}},{"cell_type":"markdown","source":"Prepare dataframe of unique patients and corresponding target","metadata":{"id":"-wHu9A2J8h6M"}},{"cell_type":"code","source":"#TRAIN_IMAGES_BASE_PATH = os.path.join(DATASET_BASE_DIR,'stage_2_train_images')\n#df = pd.read_csv('/mnt/MyDrive/Dataset/df_final.csv')\n#df_grouped = df.groupby('patientId')","metadata":{"id":"OSkjHTZoscQ2","execution":{"iopub.status.busy":"2022-06-25T05:30:41.622446Z","iopub.execute_input":"2022-06-25T05:30:41.623157Z","iopub.status.idle":"2022-06-25T05:30:41.626759Z","shell.execute_reply.started":"2022-06-25T05:30:41.6231Z","shell.execute_reply":"2022-06-25T05:30:41.625932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Remove this before final submission</b>","metadata":{"id":"rqD6-NEEsm4Y"}},{"cell_type":"code","source":"df_unique = df_grouped['Target'].aggregate('first').reset_index()","metadata":{"id":"6cPlBZLv-SI2","execution":{"iopub.status.busy":"2022-06-26T01:42:01.341294Z","iopub.execute_input":"2022-06-26T01:42:01.342116Z","iopub.status.idle":"2022-06-26T01:42:01.350747Z","shell.execute_reply.started":"2022-06-26T01:42:01.342077Z","shell.execute_reply":"2022-06-26T01:42:01.349939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X = df_unique['patientId']\ny = df_unique['Target']","metadata":{"id":"s_SVAlBg-eeq","execution":{"iopub.status.busy":"2022-06-26T01:42:01.353890Z","iopub.execute_input":"2022-06-26T01:42:01.354197Z","iopub.status.idle":"2022-06-26T01:42:01.360403Z","shell.execute_reply.started":"2022-06-26T01:42:01.354171Z","shell.execute_reply":"2022-06-26T01:42:01.359526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Number of unique patients : {X.shape[0]}')","metadata":{"id":"SkD3SOwLitNW","outputId":"15a81811-a1b8-40e9-a548-1f2e68ba30f5","execution":{"iopub.status.busy":"2022-06-26T01:42:01.361580Z","iopub.execute_input":"2022-06-26T01:42:01.363846Z","iopub.status.idle":"2022-06-26T01:42:01.372856Z","shell.execute_reply.started":"2022-06-26T01:42:01.363800Z","shell.execute_reply":"2022-06-26T01:42:01.371898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Split the patientIds into train, test and validation sets. Make sure that all three sets have the same proportion of target.","metadata":{"id":"dKhzYGa495so"}},{"cell_type":"code","source":"patientids_train, patientids_test, y_train_ignore, y_test_ignore = train_test_split(X, y, test_size = 0.3, stratify = y, random_state = 33)","metadata":{"id":"Itwz1YMvY35j","execution":{"iopub.status.busy":"2022-06-26T01:42:01.374485Z","iopub.execute_input":"2022-06-26T01:42:01.375098Z","iopub.status.idle":"2022-06-26T01:42:01.396357Z","shell.execute_reply.started":"2022-06-26T01:42:01.375062Z","shell.execute_reply":"2022-06-26T01:42:01.395665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"patientids_val, patientids_test, y_val_ignore, y_test_ignore = train_test_split(patientids_test, y_test_ignore, test_size = 0.5, stratify = y_test_ignore, random_state = 33)","metadata":{"id":"DuNIbv8Oi_w0","execution":{"iopub.status.busy":"2022-06-26T01:42:01.398245Z","iopub.execute_input":"2022-06-26T01:42:01.398809Z","iopub.status.idle":"2022-06-26T01:42:01.409242Z","shell.execute_reply.started":"2022-06-26T01:42:01.398775Z","shell.execute_reply":"2022-06-26T01:42:01.408384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Verify if all three sets have same proportion of 'Target'","metadata":{"id":"MsnvYNUC-6Fy"}},{"cell_type":"code","source":"y_train_ignore.value_counts(normalize=True)","metadata":{"id":"KGMGNQ2L-5HL","outputId":"9c0eba1b-fe16-49c0-b3d2-64132819e51e","execution":{"iopub.status.busy":"2022-06-26T01:42:01.410155Z","iopub.execute_input":"2022-06-26T01:42:01.410410Z","iopub.status.idle":"2022-06-26T01:42:01.421913Z","shell.execute_reply.started":"2022-06-26T01:42:01.410385Z","shell.execute_reply":"2022-06-26T01:42:01.420721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_val_ignore.value_counts(normalize=True)","metadata":{"id":"mc9L9ni__EPG","outputId":"dd1bd7d5-160c-49c4-b9f8-543cf4ed7c65","execution":{"iopub.status.busy":"2022-06-26T01:42:01.423590Z","iopub.execute_input":"2022-06-26T01:42:01.424308Z","iopub.status.idle":"2022-06-26T01:42:01.433898Z","shell.execute_reply.started":"2022-06-26T01:42:01.424269Z","shell.execute_reply":"2022-06-26T01:42:01.432803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_test_ignore.value_counts(normalize=True)","metadata":{"id":"0OsXAliujjeB","outputId":"b8c4d247-5d4f-4903-bf4b-c0035b49d750","execution":{"iopub.status.busy":"2022-06-26T01:42:01.437407Z","iopub.execute_input":"2022-06-26T01:42:01.437739Z","iopub.status.idle":"2022-06-26T01:42:01.447965Z","shell.execute_reply.started":"2022-06-26T01:42:01.437712Z","shell.execute_reply":"2022-06-26T01:42:01.446780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Store X-rays directory corresponding to the set(train, test and validation).  \nThe directory structure would look like :  \n![image.png](data:image/png;base64,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)","metadata":{"id":"_rYgI-LU_MWu"}},{"cell_type":"code","source":"top_dirs = ['train', 'test','val']","metadata":{"id":"K817Dj3JjoXf","execution":{"iopub.status.busy":"2022-06-26T01:42:01.449734Z","iopub.execute_input":"2022-06-26T01:42:01.450226Z","iopub.status.idle":"2022-06-26T01:42:01.454958Z","shell.execute_reply.started":"2022-06-26T01:42:01.450186Z","shell.execute_reply":"2022-06-26T01:42:01.453712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.chdir(DATASET_BASE_DIR)\nfor main_dir in top_dirs:\n  os.mkdir(main_dir)\n  os.chdir(main_dir)\n  os.mkdir('0')\n  os.mkdir('1')    \n\n  if main_dir == 'train':\n    ids = patientids_train\n  elif main_dir == 'val':\n    ids = patientids_val\n  else:\n    ids = patientids_test\n\n  for patient_id in tqdm.tqdm(ids):\n      # Open pydicom file\n      img = pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, patient_id)+'.dcm').pixel_array\n\n      if (df_unique[df_unique['patientId'] == patient_id]['Target'].values == 0):\n        parent_dir = '0'\n      else:\n        parent_dir = '1'\n\n      # Save pixel_array to png file\n      cv2.imwrite(os.path.join(parent_dir, patient_id+'.png'), img)\n\n  os.chdir('..')","metadata":{"id":"rTlEqHHF_kaY","outputId":"bcd96ee1-f6c8-4738-83b5-4546465067ea","execution":{"iopub.status.busy":"2022-06-26T01:42:01.456905Z","iopub.execute_input":"2022-06-26T01:42:01.457396Z","iopub.status.idle":"2022-06-26T01:57:16.979069Z","shell.execute_reply.started":"2022-06-26T01:42:01.457357Z","shell.execute_reply":"2022-06-26T01:57:16.978229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Configurations :-","metadata":{"id":"rXj2NwMdHnf_"}},{"cell_type":"code","source":"IMG_HEIGHT = 224\nIMG_WIDTH = 224\nBATCH_SIZE = 128","metadata":{"id":"mU62x1Lg8IW5","execution":{"iopub.status.busy":"2022-06-26T01:57:16.981618Z","iopub.execute_input":"2022-06-26T01:57:16.981901Z","iopub.status.idle":"2022-06-26T01:57:16.986563Z","shell.execute_reply.started":"2022-06-26T01:57:16.981877Z","shell.execute_reply":"2022-06-26T01:57:16.984540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create an ImageDataGenerator object with data augmentation for training data","metadata":{"id":"F9BcOWsZHvWo"}},{"cell_type":"code","source":"datagen = ImageDataGenerator(rotation_range=0.2, width_shift_range=0.05, \n                                   height_shift_range=0.05, shear_range=0.05, \n                                   zoom_range=0.05, horizontal_flip = True, \n                                   fill_mode='nearest')","metadata":{"id":"wVaXjqDC78hu","execution":{"iopub.status.busy":"2022-06-26T01:57:16.987980Z","iopub.execute_input":"2022-06-26T01:57:16.988573Z","iopub.status.idle":"2022-06-26T01:57:17.011287Z","shell.execute_reply.started":"2022-06-26T01:57:16.988536Z","shell.execute_reply":"2022-06-26T01:57:17.010305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a directory iterator with batch size of 1 just to test how the generated images would look like","metadata":{"id":"0z7MeLLxH5qt"}},{"cell_type":"code","source":"myGenerator = datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR,'train'), \n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='grayscale',\n                                          class_mode='binary',\n                                          batch_size=1)","metadata":{"id":"n3O3NUGH81Hb","outputId":"f8661d4a-ecde-49be-e922-f685cc82e1f3","execution":{"iopub.status.busy":"2022-06-26T01:57:17.012675Z","iopub.execute_input":"2022-06-26T01:57:17.013239Z","iopub.status.idle":"2022-06-26T01:57:18.206027Z","shell.execute_reply.started":"2022-06-26T01:57:17.013198Z","shell.execute_reply":"2022-06-26T01:57:18.204828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_generator_images(tgt):\n  '''\n  Function to visualize the images generated by directory iterator\n  (with augmentation) corresponding to the provided target.\n  '''\n  counter = 0\n  fig, ax = plt.subplots(1, 6, figsize = (20, 6))\n  for i in range(len(patientids_train)):\n    img, target = myGenerator.__next__()\n    if(int(target[0]) != tgt):\n      continue\n    ax[counter].imshow(np.squeeze(img[0]), cmap=plt.cm.gray);\n    counter = counter + 1\n    if(counter >= 6):\n      break\n  plt.title(int(target[0]))\n  plt.show();","metadata":{"id":"5zztbzCVAnTO","execution":{"iopub.status.busy":"2022-06-26T01:57:18.208683Z","iopub.execute_input":"2022-06-26T01:57:18.209090Z","iopub.status.idle":"2022-06-26T01:57:18.233183Z","shell.execute_reply.started":"2022-06-26T01:57:18.209049Z","shell.execute_reply":"2022-06-26T01:57:18.227456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Sample images generated for target 0","metadata":{"id":"n2ObvemuIoix"}},{"cell_type":"code","source":"show_generator_images(0)","metadata":{"id":"Y1Wxy7y2A58J","outputId":"4465d80a-defb-4994-ea68-c97d53a23779","execution":{"iopub.status.busy":"2022-06-26T01:57:18.239350Z","iopub.execute_input":"2022-06-26T01:57:18.240957Z","iopub.status.idle":"2022-06-26T01:57:19.311118Z","shell.execute_reply.started":"2022-06-26T01:57:18.240915Z","shell.execute_reply":"2022-06-26T01:57:19.310339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Sample images generated for target 1","metadata":{"id":"JWhDBty1IuSw"}},{"cell_type":"code","source":"show_generator_images(1)","metadata":{"id":"1c0fiUA6A8hX","outputId":"1c5b442e-8e84-4d94-8705-5cc030a82ca3","execution":{"iopub.status.busy":"2022-06-26T01:57:19.312581Z","iopub.execute_input":"2022-06-26T01:57:19.313555Z","iopub.status.idle":"2022-06-26T01:57:20.593208Z","shell.execute_reply.started":"2022-06-26T01:57:19.313516Z","shell.execute_reply":"2022-06-26T01:57:20.592156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Creating the train, test and validation iterators that will be in model building","metadata":{"id":"ClePQAhdJOaU"}},{"cell_type":"code","source":"train_generator = datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR,'train'), \n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='grayscale',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE)","metadata":{"id":"svWzWg0P8zJE","outputId":"105b0fb3-001c-4bfb-ee93-3b4e396c5d03","execution":{"iopub.status.busy":"2022-06-26T01:57:20.594821Z","iopub.execute_input":"2022-06-26T01:57:20.595315Z","iopub.status.idle":"2022-06-26T01:57:21.160623Z","shell.execute_reply.started":"2022-06-26T01:57:20.595272Z","shell.execute_reply":"2022-06-26T01:57:21.159552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a seperate generator(and directory iterators) for validation and test data.","metadata":{"id":"xK2cNYEkSFVW"}},{"cell_type":"code","source":"test_datagen = ImageDataGenerator()\ntest_generator = test_datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'test'),\n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='grayscale',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE,\n                                          shuffle = False)\nval_generator = test_datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'val'),\n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='grayscale',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE)","metadata":{"id":"1sJxdbFCQ1Fc","outputId":"e66b9e97-231b-492a-e6c7-14136c25e25a","execution":{"iopub.status.busy":"2022-06-26T01:57:21.162048Z","iopub.execute_input":"2022-06-26T01:57:21.162621Z","iopub.status.idle":"2022-06-26T01:57:21.388614Z","shell.execute_reply.started":"2022-06-26T01:57:21.162580Z","shell.execute_reply":"2022-06-26T01:57:21.387536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Building","metadata":{"id":"5NKamq7QJWqg"}},{"cell_type":"markdown","source":"We will start with a basic CNN model that will predict the target. In the final submission we will focus on predicting the pneumonia patches.","metadata":{"id":"dLHanLZSKlEu"}},{"cell_type":"code","source":"def simple_cnn_model():\n  model = tf.keras.Sequential()\n  model.add(tf.keras.layers.InputLayer(input_shape=(IMG_WIDTH, IMG_HEIGHT, 1)))\n  \n  model.add(tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.MaxPool2D(pool_size=(2,2)))\n\n  model.add(tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.MaxPool2D(pool_size=(2,2)))\n\n  model.add(tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3),padding = 'Same', activation ='relu'))\n  model.add(tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2)))\n\n  model.add(tf.keras.layers.Flatten())\n  model.add(tf.keras.layers.Dense(activation = 'relu', units = 256,  kernel_initializer=tf.keras.initializers.he_normal(seed)))\n  #model.add(Dense(activation = 'relu', units = 64,  kernel_initializer=initializers.he_normal(seed)))\n\n  model.add(tf.keras.layers.Dense(activation = 'sigmoid', units = 1))\n\n  return model","metadata":{"id":"D5fbWZPqcM18","execution":{"iopub.status.busy":"2022-06-26T01:57:21.390031Z","iopub.execute_input":"2022-06-26T01:57:21.390574Z","iopub.status.idle":"2022-06-26T01:57:21.406712Z","shell.execute_reply.started":"2022-06-26T01:57:21.390534Z","shell.execute_reply":"2022-06-26T01:57:21.405632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = simple_cnn_model()","metadata":{"id":"U2y9W8fkcjYe","execution":{"iopub.status.busy":"2022-06-26T01:57:21.410185Z","iopub.execute_input":"2022-06-26T01:57:21.411868Z","iopub.status.idle":"2022-06-26T01:57:25.430880Z","shell.execute_reply.started":"2022-06-26T01:57:21.411820Z","shell.execute_reply":"2022-06-26T01:57:25.429976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"opt = tf.keras.optimizers.Adam(learning_rate = 0.001, epsilon = 1e-08)","metadata":{"id":"HRuLhpILcmqv","execution":{"iopub.status.busy":"2022-06-26T01:57:25.439600Z","iopub.execute_input":"2022-06-26T01:57:25.439927Z","iopub.status.idle":"2022-06-26T01:57:25.445261Z","shell.execute_reply.started":"2022-06-26T01:57:25.439900Z","shell.execute_reply":"2022-06-26T01:57:25.444429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer = opt, loss = 'binary_crossentropy', metrics = ['accuracy'])","metadata":{"id":"P1L8br5Pcigo","execution":{"iopub.status.busy":"2022-06-26T01:57:25.446778Z","iopub.execute_input":"2022-06-26T01:57:25.447427Z","iopub.status.idle":"2022-06-26T01:57:25.469758Z","shell.execute_reply.started":"2022-06-26T01:57:25.447387Z","shell.execute_reply":"2022-06-26T01:57:25.468597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''model = tf.keras.Sequential()\nmodel.add(tf.keras.layers.InputLayer(input_shape=(IMG_WIDTH, IMG_HEIGHT, 1)))\n\nmodel.add(tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.MaxPool2D(pool_size=(2,2)))\n\nmodel.add(tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.MaxPool2D(pool_size=(2,2)))\n\nmodel.add(tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.Conv2D(filters = 128, kernel_size = (3,3),padding = 'Same', activation ='relu'))\nmodel.add(tf.keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2)))\n\nmodel.add(tf.keras.layers.Flatten())\nmodel.add(tf.keras.layers.Dense(activation = 'relu', units = 256,  kernel_initializer=tf.keras.initializers.he_normal(seed)))\n#model.add(Dense(activation = 'relu', units = 64,  kernel_initializer=initializers.he_normal(seed)))\nmodel.add(tf.keras.layers.Dense(activation = 'sigmoid', units = 1))\nopt = tf.keras.optimizers.Adam(learning_rate = 0.001, epsilon = 1e-08)\nmodel.compile(optimizer = opt, loss = 'binary_crossentropy', metrics = ['accuracy'])'''","metadata":{"id":"yKxcZv2N9WK5","execution":{"iopub.status.busy":"2022-06-25T19:56:42.650689Z","iopub.execute_input":"2022-06-25T19:56:42.651320Z","iopub.status.idle":"2022-06-25T19:56:42.658434Z","shell.execute_reply.started":"2022-06-25T19:56:42.651284Z","shell.execute_reply":"2022-06-25T19:56:42.657512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"id":"myHV1G2GGpUQ","outputId":"4089ea9c-1926-4977-c1c9-39c42b567973","execution":{"iopub.status.busy":"2022-06-26T01:57:25.471551Z","iopub.execute_input":"2022-06-26T01:57:25.471958Z","iopub.status.idle":"2022-06-26T01:57:25.481365Z","shell.execute_reply.started":"2022-06-26T01:57:25.471917Z","shell.execute_reply":"2022-06-26T01:57:25.480348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a checkpoint to save the best model","metadata":{"id":"pCUyQkxnK3q3"}},{"cell_type":"code","source":"model_checkpoint = tf.keras.callbacks.ModelCheckpoint(os.path.join(DATASET_BASE_DIR,'rsna_simple_predict.h5'), save_best_only = True, \n                                                      monitor = 'val_accuracy', mode='max', verbose = 1)","metadata":{"id":"rMUKPpmkGM3j","execution":{"iopub.status.busy":"2022-06-26T01:57:25.483152Z","iopub.execute_input":"2022-06-26T01:57:25.483819Z","iopub.status.idle":"2022-06-26T01:57:25.490041Z","shell.execute_reply.started":"2022-06-26T01:57:25.483779Z","shell.execute_reply":"2022-06-26T01:57:25.489012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_generator, epochs = 10, validation_data = val_generator, batch_size = BATCH_SIZE, callbacks = [model_checkpoint])","metadata":{"id":"1fAUK-Au9WUT","outputId":"2fa0930a-ff15-4641-dbd2-f1225f57571a","execution":{"iopub.status.busy":"2022-06-26T01:57:25.491609Z","iopub.execute_input":"2022-06-26T01:57:25.492101Z","iopub.status.idle":"2022-06-26T02:57:25.415921Z","shell.execute_reply.started":"2022-06-26T01:57:25.492062Z","shell.execute_reply":"2022-06-26T02:57:25.413136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We are getting best accuracy of approximately 81% on validation dataset.","metadata":{"id":"0w0B8O3ILQGL"}},{"cell_type":"code","source":"def plot_loss(history):\n  plt.plot(history.history['loss'], label='Loss on training data')\n  plt.plot(history.history['val_loss'], label='Loss on validation data')\n  plt.xlabel('Epoch')\n  plt.ylabel('Loss')\n  plt.title('Loss vs Epoch')\n  plt.legend()\n  plt.grid(True)\n  plt.show();","metadata":{"id":"1xeDPKRZLf49","execution":{"iopub.status.busy":"2022-06-26T02:57:25.420584Z","iopub.execute_input":"2022-06-26T02:57:25.423066Z","iopub.status.idle":"2022-06-26T02:57:25.433762Z","shell.execute_reply.started":"2022-06-26T02:57:25.423022Z","shell.execute_reply":"2022-06-26T02:57:25.432341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_accuracy(history):\n  plt.plot(history.history['accuracy'], label='Accuracy on training data')\n  plt.plot(history.history['val_accuracy'], label='Accuracy on validation data')\n  plt.xlabel('Epoch')\n  plt.ylabel('Accuracy')\n  plt.title('Accuracy vs Epoch')\n  plt.legend()\n  plt.grid(True)\n  plt.show();","metadata":{"id":"yPbDqOAQ0ZqA","execution":{"iopub.status.busy":"2022-06-26T02:57:25.435387Z","iopub.execute_input":"2022-06-26T02:57:25.436068Z","iopub.status.idle":"2022-06-26T02:57:25.472524Z","shell.execute_reply.started":"2022-06-26T02:57:25.436028Z","shell.execute_reply":"2022-06-26T02:57:25.471410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_loss(history)","metadata":{"id":"ZX_ZueoELkww","outputId":"28a4bcca-7d99-4e07-fd9d-320b5841b4ea","execution":{"iopub.status.busy":"2022-06-26T02:57:25.474424Z","iopub.execute_input":"2022-06-26T02:57:25.474940Z","iopub.status.idle":"2022-06-26T02:57:25.756662Z","shell.execute_reply.started":"2022-06-26T02:57:25.474896Z","shell.execute_reply":"2022-06-26T02:57:25.755830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_accuracy(history)","metadata":{"id":"q-FHG39A0xHK","outputId":"0cd2968a-7350-419d-bd8c-492727731a04","execution":{"iopub.status.busy":"2022-06-26T02:57:25.758162Z","iopub.execute_input":"2022-06-26T02:57:25.758583Z","iopub.status.idle":"2022-06-26T02:57:25.971210Z","shell.execute_reply.started":"2022-06-26T02:57:25.758545Z","shell.execute_reply":"2022-06-26T02:57:25.970413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load the best model and check accuracy on test data","metadata":{"id":"LazgtB8OLCMr"}},{"cell_type":"code","source":"best_model = tf.keras.models.load_model(os.path.join(DATASET_BASE_DIR,'rsna_simple_predict.h5'))","metadata":{"id":"4ZqRuwmnLaFa","execution":{"iopub.status.busy":"2022-06-26T02:57:25.972387Z","iopub.execute_input":"2022-06-26T02:57:25.973148Z","iopub.status.idle":"2022-06-26T02:57:29.088105Z","shell.execute_reply.started":"2022-06-26T02:57:25.973097Z","shell.execute_reply":"2022-06-26T02:57:29.087153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"score = best_model.evaluate(test_generator)","metadata":{"id":"YCjnQFMN9WdQ","outputId":"f4b81c40-6718-48d1-88c6-56f6d3586be0","execution":{"iopub.status.busy":"2022-06-26T02:57:29.089656Z","iopub.execute_input":"2022-06-26T02:57:29.090067Z","iopub.status.idle":"2022-06-26T02:58:53.076255Z","shell.execute_reply.started":"2022-06-26T02:57:29.090028Z","shell.execute_reply":"2022-06-26T02:58:53.075311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Best model has accuracy : {round(score[1]*100, 2)}% and loss : {round(score[0], 2)} on test data')","metadata":{"id":"RDDY9LK79WhC","outputId":"8930948c-dbdb-47f6-fa5e-57c44a634819","execution":{"iopub.status.busy":"2022-06-26T02:58:53.077592Z","iopub.execute_input":"2022-06-26T02:58:53.077897Z","iopub.status.idle":"2022-06-26T02:58:53.084511Z","shell.execute_reply.started":"2022-06-26T02:58:53.077869Z","shell.execute_reply":"2022-06-26T02:58:53.083351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_test_predict = best_model.predict(test_generator)","metadata":{"id":"jLQyEOEf9WlD","execution":{"iopub.status.busy":"2022-06-26T02:58:53.086021Z","iopub.execute_input":"2022-06-26T02:58:53.086658Z","iopub.status.idle":"2022-06-26T02:59:32.690105Z","shell.execute_reply.started":"2022-06-26T02:58:53.086620Z","shell.execute_reply":"2022-06-26T02:59:32.689175Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Confusion Matrix(Test Data)')\ndf_cm = pd.DataFrame(confusion_matrix(test_generator.classes, y_test_predict > 0.5))\ndf_cm.index.name = 'Actual'\ndf_cm.columns.name = 'Predicted'\ndisplay(df_cm)","metadata":{"id":"tXnatNkm9WzP","outputId":"c6f25d36-1e95-4ffc-85ee-b405e22f0dfb","execution":{"iopub.status.busy":"2022-06-26T02:59:32.691426Z","iopub.execute_input":"2022-06-26T02:59:32.691842Z","iopub.status.idle":"2022-06-26T02:59:32.711253Z","shell.execute_reply.started":"2022-06-26T02:59:32.691803Z","shell.execute_reply":"2022-06-26T02:59:32.710499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(classification_report(test_generator.classes, y_test_predict > 0.5))","metadata":{"id":"taU6h_CMHPdr","outputId":"fa03918c-8574-4113-be14-86ddef2b6068","execution":{"iopub.status.busy":"2022-06-26T02:59:32.712391Z","iopub.execute_input":"2022-06-26T02:59:32.713429Z","iopub.status.idle":"2022-06-26T02:59:32.732064Z","shell.execute_reply.started":"2022-06-26T02:59:32.713384Z","shell.execute_reply":"2022-06-26T02:59:32.731149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We are getting a decent accuracy of approximately 81% on test data. \nF-1 Score for class 0 is 88% while for class 1 it is 51% which is quite low.","metadata":{"id":"V7BeadVfR7Ga"}},{"cell_type":"markdown","source":"Storing some of the metrics and model-related information in table that can be used later for performance comparison. The table shall contain:-\n- Model Name (For identifying the approach used)\n- Accuracy on training dataset\n- Accuracy on test dataset\n- 'Pneumonia Positive' class F1-score\n- 'Pneumonia Positive' class recall\n- 'Pneumonia Positive' class precision\n- Trained on undersampled dataset?\n- Class Threshold","metadata":{"id":"30EAul4BQn1s"}},{"cell_type":"code","source":"models_table = []","metadata":{"id":"uF10Om6aP_9Q","execution":{"iopub.status.busy":"2022-06-26T02:59:32.733536Z","iopub.execute_input":"2022-06-26T02:59:32.734656Z","iopub.status.idle":"2022-06-26T02:59:32.739794Z","shell.execute_reply.started":"2022-06-26T02:59:32.734601Z","shell.execute_reply":"2022-06-26T02:59:32.738491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models_table.append({'Name' : 'Simple CNN', \n                     'Train_Accuracy' : round(best_model.evaluate(train_generator)[1]*100, 2), \n                     'Test_Accuracy' : round(score[1]*100, 2),\n                     'Class_1_F1_Score' : f1_score(test_generator.classes, y_test_predict > 0.5),\n                     'Class_1_Recall' : recall_score(test_generator.classes, y_test_predict > 0.5),\n                     'Class_1_Precision' : precision_score(test_generator.classes, y_test_predict > 0.5),\n                     'UnderSampling_Used' : 0,\n                     })","metadata":{"id":"ZDoUWcccTCi9","outputId":"995eb6e8-4ee0-4b97-c44c-e5e4cd13dde1","execution":{"iopub.status.busy":"2022-06-26T02:59:32.741384Z","iopub.execute_input":"2022-06-26T02:59:32.742685Z","iopub.status.idle":"2022-06-26T03:04:43.283945Z","shell.execute_reply.started":"2022-06-26T02:59:32.742643Z","shell.execute_reply":"2022-06-26T03:04:43.282951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Next we will train the same model on undersampled data to see if data balancing has any effect","metadata":{"id":"3DPVBEART6KB"}},{"cell_type":"code","source":"# Init RandomUnderSampler\nrand_unsampler = RandomUnderSampler(random_state = 33)","metadata":{"id":"o8ivTbKYT4yU","execution":{"iopub.status.busy":"2022-06-26T03:04:43.286756Z","iopub.execute_input":"2022-06-26T03:04:43.287544Z","iopub.status.idle":"2022-06-26T03:04:43.292407Z","shell.execute_reply.started":"2022-06-26T03:04:43.287496Z","shell.execute_reply":"2022-06-26T03:04:43.291349Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rand_unsampler = rand_unsampler.fit(np.array(patientids_train.to_list()).reshape(-1, 1), y_train_ignore)","metadata":{"id":"-NJhHMk6UYj-","execution":{"iopub.status.busy":"2022-06-26T03:04:43.294467Z","iopub.execute_input":"2022-06-26T03:04:43.294983Z","iopub.status.idle":"2022-06-26T03:04:43.336564Z","shell.execute_reply.started":"2022-06-26T03:04:43.294937Z","shell.execute_reply":"2022-06-26T03:04:43.335536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"patientids_train_rus, y_train_ignore_rus = rand_unsampler.fit_resample(np.array(patientids_train.to_list()).reshape(-1, 1), y_train_ignore)","metadata":{"id":"EnSmntKCUlAs","execution":{"iopub.status.busy":"2022-06-26T03:04:43.338296Z","iopub.execute_input":"2022-06-26T03:04:43.338909Z","iopub.status.idle":"2022-06-26T03:04:43.364281Z","shell.execute_reply.started":"2022-06-26T03:04:43.338705Z","shell.execute_reply":"2022-06-26T03:04:43.363321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Check proportion of the two classes in undersampled dataset","metadata":{"id":"FZ2a_gVQU8B7"}},{"cell_type":"code","source":"y_train_ignore_rus.value_counts(normalize=True)","metadata":{"id":"zYIc_dk0U67x","outputId":"5c5791c0-1a65-48ee-f4bb-6174befcf223","execution":{"iopub.status.busy":"2022-06-26T03:04:43.365824Z","iopub.execute_input":"2022-06-26T03:04:43.366205Z","iopub.status.idle":"2022-06-26T03:04:43.390271Z","shell.execute_reply.started":"2022-06-26T03:04:43.366169Z","shell.execute_reply":"2022-06-26T03:04:43.388947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a seperate directory for undersampled training set","metadata":{"id":"JC0xMzbkVf4f"}},{"cell_type":"code","source":"os.chdir(DATASET_BASE_DIR)\nos.mkdir('train_undersampled')\nos.chdir('train_undersampled')\nos.mkdir('0')\nos.mkdir('1')\n\nfor patient_id in tqdm.tqdm(patientids_train_rus.squeeze()):\n  # Open pydicom file\n  img = pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, patient_id)+'.dcm').pixel_array\n  \n  if (df_unique[df_unique['patientId'] == patient_id]['Target'].values == 0):\n    parent_dir = '0'\n  else:\n    parent_dir = '1'\n  \n  # Save pixel_array to png file\n  cv2.imwrite(os.path.join(parent_dir, patient_id+'.png'), img)","metadata":{"id":"Z792hwx8VZRm","outputId":"1e493a1b-3c55-4e54-bd58-95031d15e9f0","execution":{"iopub.status.busy":"2022-06-26T03:04:43.391846Z","iopub.execute_input":"2022-06-26T03:04:43.392366Z","iopub.status.idle":"2022-06-26T03:09:52.451766Z","shell.execute_reply.started":"2022-06-26T03:04:43.392323Z","shell.execute_reply":"2022-06-26T03:09:52.450814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create a generator for the undersampled training set","metadata":{"id":"5iSAZwnwboSK"}},{"cell_type":"code","source":"train_generator_undersampled = datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'train_undersampled'), \n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='grayscale',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE)","metadata":{"id":"f83E8FWMbnpU","outputId":"4738636f-960e-4969-cb32-d23d1095c842","execution":{"iopub.status.busy":"2022-06-26T03:09:52.453066Z","iopub.execute_input":"2022-06-26T03:09:52.454967Z","iopub.status.idle":"2022-06-26T03:09:52.794824Z","shell.execute_reply.started":"2022-06-26T03:09:52.454922Z","shell.execute_reply":"2022-06-26T03:09:52.793896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Init simple CNN model","metadata":{"id":"BHZ_YMEDcwyB"}},{"cell_type":"code","source":"model = simple_cnn_model()","metadata":{"id":"N1H3LzXHcvHv","execution":{"iopub.status.busy":"2022-06-26T03:09:52.796012Z","iopub.execute_input":"2022-06-26T03:09:52.796898Z","iopub.status.idle":"2022-06-26T03:09:52.901035Z","shell.execute_reply.started":"2022-06-26T03:09:52.796858Z","shell.execute_reply":"2022-06-26T03:09:52.900161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"opt = tf.keras.optimizers.Adam(learning_rate = 0.001, epsilon = 1e-08)\nmodel.compile(optimizer = opt, loss = 'binary_crossentropy', metrics = ['accuracy'])","metadata":{"id":"EtoHgGi4c4Xn","execution":{"iopub.status.busy":"2022-06-26T03:09:52.902409Z","iopub.execute_input":"2022-06-26T03:09:52.902806Z","iopub.status.idle":"2022-06-26T03:09:52.914398Z","shell.execute_reply.started":"2022-06-26T03:09:52.902768Z","shell.execute_reply":"2022-06-26T03:09:52.913463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create Checkpoint","metadata":{"id":"Jmy7kCfmdIt0"}},{"cell_type":"code","source":"model_checkpoint = tf.keras.callbacks.ModelCheckpoint(os.path.join(DATASET_BASE_DIR,'rsna_simple_predict_rus.h5'), save_best_only = True, \n                                                      monitor = 'val_accuracy', mode='max', verbose = 1)","metadata":{"id":"TMROFY0qdK_L","execution":{"iopub.status.busy":"2022-06-26T03:09:52.915871Z","iopub.execute_input":"2022-06-26T03:09:52.916618Z","iopub.status.idle":"2022-06-26T03:09:52.922512Z","shell.execute_reply.started":"2022-06-26T03:09:52.916576Z","shell.execute_reply":"2022-06-26T03:09:52.921693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(train_generator_undersampled, epochs = 10, validation_data = val_generator, batch_size = BATCH_SIZE, callbacks = [model_checkpoint])","metadata":{"id":"0EJGXtv2dTyz","outputId":"c367021e-dcb0-484e-99d3-4f0ad8ef6da3","execution":{"iopub.status.busy":"2022-06-26T03:09:52.923801Z","iopub.execute_input":"2022-06-26T03:09:52.924755Z","iopub.status.idle":"2022-06-26T03:37:19.040562Z","shell.execute_reply.started":"2022-06-26T03:09:52.924716Z","shell.execute_reply":"2022-06-26T03:37:19.039612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_loss(history)","metadata":{"id":"aymIqWlTdZqR","outputId":"4aae6d17-1a8d-4bae-93f3-fe82517a8711","execution":{"iopub.status.busy":"2022-06-26T03:37:19.042537Z","iopub.execute_input":"2022-06-26T03:37:19.042955Z","iopub.status.idle":"2022-06-26T03:37:19.259284Z","shell.execute_reply.started":"2022-06-26T03:37:19.042916Z","shell.execute_reply":"2022-06-26T03:37:19.258354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_accuracy(history)","metadata":{"id":"9QkMkFKTdaRR","outputId":"a10d8ba1-e616-453a-85fe-3e9aae517410","execution":{"iopub.status.busy":"2022-06-26T03:37:19.260905Z","iopub.execute_input":"2022-06-26T03:37:19.261515Z","iopub.status.idle":"2022-06-26T03:37:19.486518Z","shell.execute_reply.started":"2022-06-26T03:37:19.261462Z","shell.execute_reply":"2022-06-26T03:37:19.485706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load the best model and check accuracy on test data","metadata":{"id":"T_Xu7TaDfYsW"}},{"cell_type":"code","source":"best_model = tf.keras.models.load_model(os.path.join(DATASET_BASE_DIR,'rsna_simple_predict_rus.h5'))","metadata":{"id":"5Zbr7B__fXzo","execution":{"iopub.status.busy":"2022-06-26T03:37:19.488027Z","iopub.execute_input":"2022-06-26T03:37:19.488665Z","iopub.status.idle":"2022-06-26T03:37:20.573762Z","shell.execute_reply.started":"2022-06-26T03:37:19.488622Z","shell.execute_reply":"2022-06-26T03:37:20.572853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"score = best_model.evaluate(test_generator)","metadata":{"id":"0dLxRAxifTiq","outputId":"ca74b53d-559c-4fe6-8e47-ae98defc43f1","execution":{"iopub.status.busy":"2022-06-26T03:37:20.575324Z","iopub.execute_input":"2022-06-26T03:37:20.575731Z","iopub.status.idle":"2022-06-26T03:38:44.883252Z","shell.execute_reply.started":"2022-06-26T03:37:20.575692Z","shell.execute_reply":"2022-06-26T03:38:44.882261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Best model has accuracy : {round(score[1]*100, 2)}% and loss : {round(score[0], 2)} on test data')","metadata":{"id":"MtGfIj7NfmgV","outputId":"172bfefd-53ef-4f4e-a5f6-116f4af59f34","execution":{"iopub.status.busy":"2022-06-26T03:38:44.884797Z","iopub.execute_input":"2022-06-26T03:38:44.885129Z","iopub.status.idle":"2022-06-26T03:38:44.890681Z","shell.execute_reply.started":"2022-06-26T03:38:44.885100Z","shell.execute_reply":"2022-06-26T03:38:44.889538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_test_predict = best_model.predict(test_generator)","metadata":{"id":"1hkyQZjWfqW6","execution":{"iopub.status.busy":"2022-06-26T03:38:44.892419Z","iopub.execute_input":"2022-06-26T03:38:44.893069Z","iopub.status.idle":"2022-06-26T03:39:24.259620Z","shell.execute_reply.started":"2022-06-26T03:38:44.893035Z","shell.execute_reply":"2022-06-26T03:39:24.258641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f'Confusion Matrix(Test Data)')\ndf_cm = pd.DataFrame(confusion_matrix(test_generator.classes, y_test_predict > 0.5))\ndf_cm.index.name = 'Actual'\ndf_cm.columns.name = 'Predicted'\ndisplay(df_cm)","metadata":{"id":"Rt5853_MfuCd","outputId":"ff597cfe-d012-46d6-ca08-9722846a2930","execution":{"iopub.status.busy":"2022-06-26T03:39:24.261079Z","iopub.execute_input":"2022-06-26T03:39:24.261861Z","iopub.status.idle":"2022-06-26T03:39:24.286335Z","shell.execute_reply.started":"2022-06-26T03:39:24.261819Z","shell.execute_reply":"2022-06-26T03:39:24.285523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(classification_report(test_generator.classes, y_test_predict > 0.5))","metadata":{"id":"CBzHPHaIfvU_","outputId":"f5a61e61-98ea-41b7-b3d0-55df975adc57","execution":{"iopub.status.busy":"2022-06-26T03:39:24.287726Z","iopub.execute_input":"2022-06-26T03:39:24.288532Z","iopub.status.idle":"2022-06-26T03:39:24.307158Z","shell.execute_reply.started":"2022-06-26T03:39:24.288477Z","shell.execute_reply":"2022-06-26T03:39:24.306140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Although the model accuracy has reduced but we are seeing good improvement in pneumonia class recall. Recall is what we believe is important for this problem because we may not want to let any pneumonia patient go undetected even if False positives increase slightly.","metadata":{}},{"cell_type":"code","source":"models_table.append({'Name' : 'Simple CNN', \n                     'Train_Accuracy' : round(best_model.evaluate(train_generator_undersampled)[1]*100, 2), \n                     'Test_Accuracy' : round(score[1]*100, 2),\n                     'Class_1_F1_Score' : f1_score(test_generator.classes, y_test_predict > 0.5),\n                     'Class_1_Recall' : recall_score(test_generator.classes, y_test_predict > 0.5),\n                     'Class_1_Precision' : precision_score(test_generator.classes, y_test_predict > 0.5),\n                     'UnderSampling_Used' : 1,\n                     })","metadata":{"id":"YUGW4WThf31l","outputId":"c4e595a8-d556-4286-df1d-8b56d85dbea5","execution":{"iopub.status.busy":"2022-06-26T03:39:24.308887Z","iopub.execute_input":"2022-06-26T03:39:24.309341Z","iopub.status.idle":"2022-06-26T03:41:18.325004Z","shell.execute_reply.started":"2022-06-26T03:39:24.309297Z","shell.execute_reply":"2022-06-26T03:41:18.324123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Next we will use Transfer Learning with following CNN archtectures :-\n  1. Resnet-50\n  2. VGG16\n  3. Mobilenet","metadata":{"id":"s5IqxCJRgD64"}},{"cell_type":"markdown","source":"Create Generators to be used","metadata":{"id":"TVFxzIDHhHXe"}},{"cell_type":"code","source":"train_generator = datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'train'),\n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='rgb',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE)\n\ntrain_generator_undersampled = datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'train_undersampled'),\n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='rgb',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE)\n\ntest_generator = test_datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'test'),\n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='rgb',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE,\n                                          shuffle = False)\n\nval_generator = test_datagen.flow_from_directory(os.path.join(DATASET_BASE_DIR, 'val'),\n                                          target_size=(IMG_HEIGHT, IMG_WIDTH),\n                                          color_mode='rgb',\n                                          class_mode='binary',\n                                          batch_size=BATCH_SIZE)","metadata":{"id":"d0MkYE1jgsI5","outputId":"aa113d58-a4bd-4dcd-81c4-7945475b23a7","execution":{"iopub.status.busy":"2022-06-26T03:41:18.326347Z","iopub.execute_input":"2022-06-26T03:41:18.327176Z","iopub.status.idle":"2022-06-26T03:41:19.437682Z","shell.execute_reply.started":"2022-06-26T03:41:18.327129Z","shell.execute_reply":"2022-06-26T03:41:19.436734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Function to create Resnet-50 model\n\n","metadata":{"id":"PmpfZQO-hmFY"}},{"cell_type":"code","source":"def resnet_50_model():\n  backend = tf.keras.applications.ResNet50(weights='imagenet', input_shape=(IMG_HEIGHT, IMG_WIDTH, 3), include_top=False)\n\n  # Set this parameter to make sure it's not being trained\n  backend.trainable = False\n\n  # Set the input layer\n  input_ = tf.keras.Input(shape=(IMG_HEIGHT, IMG_WIDTH, 3))\n\n  # Set the backend layer\n  x = backend(input_, training=False)\n\n  # Set the pooling layer\n  x = tf.keras.layers.GlobalAveragePooling2D()(x)\n\n  # Set the final layer with sigmoid activation function\n  output_ = tf.keras.layers.Dense(1, activation='sigmoid')(x)\n\n  # Create the new model object\n  model = tf.keras.Model(input_, output_)\n\n  return model","metadata":{"id":"YlSuGtdvhcor","execution":{"iopub.status.busy":"2022-06-26T03:41:19.438876Z","iopub.execute_input":"2022-06-26T03:41:19.439866Z","iopub.status.idle":"2022-06-26T03:41:19.446969Z","shell.execute_reply.started":"2022-06-26T03:41:19.439824Z","shell.execute_reply":"2022-06-26T03:41:19.446088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Function to create VGG16 model","metadata":{"id":"d0LlNB4_jC-a"}},{"cell_type":"code","source":"def vgg16_model():\n  backend = tf.keras.applications.VGG16(weights='imagenet', input_shape=(IMG_HEIGHT, IMG_WIDTH, 3), include_top=False)\n\n  backend.trainable = False\n\n  # Set the input layer\n  input_ = tf.keras.Input(shape=(IMG_HEIGHT, IMG_WIDTH, 3))\n\n  # Set the feature extractor layer\n  x = backend(input_, training=False)\n\n  # Set the pooling layer\n  x = tf.keras.layers.GlobalAveragePooling2D()(x)\n\n  # Set the final layer with sigmoid activation function\n  output_ = tf.keras.layers.Dense(1, activation='sigmoid')(x)\n\n  # Create the new model object\n  model = tf.keras.Model(input_, output_)\n\n  return model","metadata":{"id":"YilX4TJ-jCIB","execution":{"iopub.status.busy":"2022-06-26T03:41:19.448591Z","iopub.execute_input":"2022-06-26T03:41:19.449304Z","iopub.status.idle":"2022-06-26T03:41:19.462629Z","shell.execute_reply.started":"2022-06-26T03:41:19.449265Z","shell.execute_reply":"2022-06-26T03:41:19.461662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Function to create Mobilenet model","metadata":{"id":"_EQ5UO9lm2Pp"}},{"cell_type":"code","source":"def mobilenet_model():\n  feature_extractor = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), weights=\"imagenet\", include_top=False, alpha=0.35)\n\n  # Set this parameter to make sure it's not being trained\n  feature_extractor.trainable = False\n\n  # Set the input layer\n  input_ = tf.keras.Input(shape=(224, 224, 3))\n\n  # Set the feature extractor layer\n  x = feature_extractor(input_, training=False)\n\n  # Set the pooling layer\n  x = tf.keras.layers.GlobalAveragePooling2D()(x)\n  output = tf.keras.layers.BatchNormalization()(x)\n  output_ = tf.keras.layers.Dense(256, activation='relu')(x)\n  output = tf.keras.layers.BatchNormalization()(x)\n  output_ = tf.keras.layers.Dense(128, activation='relu')(x)\n  output = tf.keras.layers.BatchNormalization()(x)\n\n  # Set the final layer with sigmoid activation function\n  output_ = tf.keras.layers.Dense(1, activation='sigmoid')(x)\n\n  # Create the new model object\n  model = tf.keras.Model(input_, output_)\n\n  return model","metadata":{"id":"nd1DkxSujH_o","execution":{"iopub.status.busy":"2022-06-26T03:41:19.464463Z","iopub.execute_input":"2022-06-26T03:41:19.465291Z","iopub.status.idle":"2022-06-26T03:41:19.478367Z","shell.execute_reply.started":"2022-06-26T03:41:19.465246Z","shell.execute_reply":"2022-06-26T03:41:19.477488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Train all models in a loop","metadata":{"id":"-xazW-qknNsn"}},{"cell_type":"code","source":"models_input = [\n                {'name' : 'Resnet-50', 'ckpt_name' : os.path.join(DATASET_BASE_DIR,'rsna_predict_resnet.h5'), 'undersample' : 0, 'epochs' : 10},\n                {'name' : 'Resnet-50', 'ckpt_name' : os.path.join(DATASET_BASE_DIR,'rsna_predict_resnet_undersampled.h5'), 'undersample' : 1, 'epochs' : 10},\n                {'name' : 'VGG16', 'ckpt_name' : os.path.join(DATASET_BASE_DIR,'rsna_predict_vgg16.h5'), 'undersample' : 0, 'epochs' : 10},\n                {'name' : 'VGG16', 'ckpt_name' : os.path.join(DATASET_BASE_DIR,'rsna_predict_vgg16_undersampled.h5'), 'undersample' : 1, 'epochs' : 10},\n                {'name' : 'Mobilenet', 'ckpt_name' : os.path.join(DATASET_BASE_DIR,'rsna_predict_mobilenet.h5'), 'undersample' : 0, 'epochs' : 10},\n                {'name' : 'Mobilenet', 'ckpt_name' : os.path.join(DATASET_BASE_DIR,'rsna_predict_mobilenet_undersampled.h5'), 'undersample' : 1, 'epochs' : 10},\n]\n\nnum_models = len(models_input)","metadata":{"id":"VeBsV5UAjICe","execution":{"iopub.status.busy":"2022-06-26T03:41:19.480215Z","iopub.execute_input":"2022-06-26T03:41:19.481043Z","iopub.status.idle":"2022-06-26T03:41:19.493975Z","shell.execute_reply.started":"2022-06-26T03:41:19.480999Z","shell.execute_reply":"2022-06-26T03:41:19.493002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for model_entry in models_input:\n  print('\\n\\n*************************************************************************************************************************')\n  print('Training model ', model_entry['name'], 'with undersampling', 'enabled' if model_entry['undersample'] == 1 else 'disabled')\n  print('*************************************************************************************************************************')\n\n  # Create model\n  if model_entry['name'] == 'Resnet-50':\n    model = resnet_50_model()\n  elif model_entry['name'] == 'VGG16':\n    model = vgg16_model()\n  elif model_entry['name'] == 'Mobilenet':\n    model = mobilenet_model()\n  else:\n    print('Unsupported model : ', model_entry['name'])\n\n  # Compile model\n  model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n\n  # Show model summary\n  model.summary()\n\n  # Create Checkpoint\n  model_checkpoint = tf.keras.callbacks.ModelCheckpoint(model_entry['ckpt_name'], save_best_only = True, \n                                                      monitor = 'val_accuracy', mode='max', verbose = 1)\n  \n  # Train model\n  history = model.fit(train_generator_undersampled if model_entry['undersample'] == 1 else train_generator, \n                      epochs = model_entry['epochs'], validation_data = val_generator, batch_size = BATCH_SIZE, callbacks = [model_checkpoint])\n  \n  # Load the best model\n  best_model = tf.keras.models.load_model(model_entry['ckpt_name'])\n\n  # Evaluate on test data\n  score = best_model.evaluate(test_generator)\n  print(f'Best model has accuracy : {round(score[1]*100, 2)}% and loss : {round(score[0], 2)} on test data')\n\n  # Confusion Matrix and Classification report\n  y_test_predict = best_model.predict(test_generator)\n\n  # Use default threshold for now\n  print(f'Confusion Matrix(Test Data)')\n  df_cm = pd.DataFrame(confusion_matrix(test_generator.classes, y_test_predict > 0.5))\n  df_cm.index.name = 'Actual'\n  df_cm.columns.name = 'Predicted'\n  display(df_cm)\n\n  print(classification_report(test_generator.classes, y_test_predict > 0.5))\n\n  # Append the results in models_data_table list\n  models_table.append({'Name' : model_entry['name'], \n                     'Train_Accuracy' : round(best_model.evaluate(train_generator_undersampled if model_entry['undersample'] == 1 else train_generator)[1]*100, 2), \n                     'Test_Accuracy' : round(score[1]*100, 2),\n                     'Class_1_F1_Score' : f1_score(test_generator.classes, y_test_predict > 0.5),\n                     'Class_1_Recall' : recall_score(test_generator.classes, y_test_predict > 0.5),\n                     'Class_1_Precision' : precision_score(test_generator.classes, y_test_predict > 0.5),\n                     'UnderSampling_Used' : model_entry['undersample'],\n                     })","metadata":{"id":"1oT_EWHNjIFA","outputId":"de124ba7-39db-414b-f960-48ade51f16de","execution":{"iopub.status.busy":"2022-06-26T03:41:19.495892Z","iopub.execute_input":"2022-06-26T03:41:19.496798Z","iopub.status.idle":"2022-06-26T10:41:55.074613Z","shell.execute_reply.started":"2022-06-26T03:41:19.496751Z","shell.execute_reply":"2022-06-26T10:41:55.071734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.DataFrame(models_table)","metadata":{"id":"MVbB8t66jIH5","execution":{"iopub.status.busy":"2022-06-26T10:41:55.079584Z","iopub.execute_input":"2022-06-26T10:41:55.080761Z","iopub.status.idle":"2022-06-26T10:41:55.135353Z","shell.execute_reply.started":"2022-06-26T10:41:55.080723Z","shell.execute_reply":"2022-06-26T10:41:55.134493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Of all the models and techniques we tried, VGG16 trained on undersampled dataset has good overall performance(considering accuracy, recall and F1-score). Although recall of mobilenet is highest but overall performance of VGG16 seems pretty good.","metadata":{}},{"cell_type":"markdown","source":"Next, we'll see if we can tweak threshold a bit to get better results on test dataset. For this we will load the best performing model from the above table.","metadata":{}},{"cell_type":"code","source":"#!ls ./rsna-pneumonia-detection-challenge/train_undersampled","metadata":{"execution":{"iopub.status.busy":"2022-06-25T13:27:56.726888Z","iopub.execute_input":"2022-06-25T13:27:56.727299Z","iopub.status.idle":"2022-06-25T13:27:57.577188Z","shell.execute_reply.started":"2022-06-25T13:27:56.727263Z","shell.execute_reply":"2022-06-25T13:27:57.576189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!ls","metadata":{"execution":{"iopub.status.busy":"2022-06-25T13:30:25.294067Z","iopub.execute_input":"2022-06-25T13:30:25.295015Z","iopub.status.idle":"2022-06-25T13:30:26.218527Z","shell.execute_reply.started":"2022-06-25T13:30:25.294968Z","shell.execute_reply":"2022-06-25T13:30:26.217412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#from IPython.display import FileLink\n#os.chdir('/kaggle/working')\n#FileLink(r'./rsna-pneumonia-detection-challenge/train_undersampled/rsna_simple_predict_rus.h5')\n#os.chdir('/kaggle/working/rsna-pneumonia-detection-challenge/train_undersampled/')","metadata":{"execution":{"iopub.status.busy":"2022-06-25T13:30:29.134628Z","iopub.execute_input":"2022-06-25T13:30:29.13579Z","iopub.status.idle":"2022-06-25T13:30:29.142807Z","shell.execute_reply.started":"2022-06-25T13:30:29.135736Z","shell.execute_reply":"2022-06-25T13:30:29.141185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_model_chkp_name = os.path.join(DATASET_BASE_DIR, 'rsna_predict_mobilenet_undersampled.h5')","metadata":{"execution":{"iopub.status.busy":"2022-06-26T10:44:00.804340Z","iopub.execute_input":"2022-06-26T10:44:00.804876Z","iopub.status.idle":"2022-06-26T10:44:00.809959Z","shell.execute_reply.started":"2022-06-26T10:44:00.804838Z","shell.execute_reply":"2022-06-26T10:44:00.808630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load best model","metadata":{}},{"cell_type":"code","source":"best_model = tf.keras.models.load_model(best_model_chkp_name)","metadata":{"execution":{"iopub.status.busy":"2022-06-26T10:44:06.209645Z","iopub.execute_input":"2022-06-26T10:44:06.210246Z","iopub.status.idle":"2022-06-26T10:44:07.679779Z","shell.execute_reply.started":"2022-06-26T10:44:06.210210Z","shell.execute_reply":"2022-06-26T10:44:07.678819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Predict on test dataset","metadata":{}},{"cell_type":"code","source":"y_test_predict = best_model.predict(test_generator)","metadata":{"execution":{"iopub.status.busy":"2022-06-26T10:44:11.850093Z","iopub.execute_input":"2022-06-26T10:44:11.850506Z","iopub.status.idle":"2022-06-26T10:44:57.458539Z","shell.execute_reply.started":"2022-06-26T10:44:11.850451Z","shell.execute_reply":"2022-06-26T10:44:57.457531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Check classification report with probabilities of 0.45, 0.4, 0.35, 0.3","metadata":{}},{"cell_type":"code","source":"probabilities = [0.45, 0.4, 0.35, 0.3]","metadata":{"execution":{"iopub.status.busy":"2022-06-26T10:45:18.578755Z","iopub.execute_input":"2022-06-26T10:45:18.579183Z","iopub.status.idle":"2022-06-26T10:45:18.588064Z","shell.execute_reply.started":"2022-06-26T10:45:18.579149Z","shell.execute_reply":"2022-06-26T10:45:18.587040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for p in probabilities:\n    print('*********************************************')\n    print(f'Classification report with probability = {p}')\n    print('*********************************************')\n    print(classification_report(test_generator.classes, y_test_predict > p))","metadata":{"execution":{"iopub.status.busy":"2022-06-26T10:45:20.658743Z","iopub.execute_input":"2022-06-26T10:45:20.659124Z","iopub.status.idle":"2022-06-26T10:45:20.703954Z","shell.execute_reply.started":"2022-06-26T10:45:20.659097Z","shell.execute_reply":"2022-06-26T10:45:20.702836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The probability 0.35 seems to have decent metrics. We'll use 0.35 as threshold for the final model.","metadata":{"id":"-Xaxk_LPvIH1"}},{"cell_type":"markdown","source":"<b>Predicting Pneumonia Patches</b>","metadata":{}},{"cell_type":"markdown","source":"So far we have worked on classifying the patients. Next, we'll work on predicting the pneumonia patches of the pneumonia patients and finally we'll integrate the two models(one for classification and other for patches prediction).\n","metadata":{"id":"w9rw77nzws6F"}},{"cell_type":"markdown","source":"Before we build unet model, we'll need to prepare data for training and testing model. For training and validating u-net model, we need images and corresponding masks that have the pneumonia patches. This is how the directory structure would look like :-  \n![image.png](attachment:379c0265-992f-4bc0-99a1-f4fef0f6abaa.png)","metadata":{"id":"YX9LmZ830Qdm"},"attachments":{"379c0265-992f-4bc0-99a1-f4fef0f6abaa.png":{"image/png":"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"}}},{"cell_type":"code","source":"# Freeing up some space\nrmtree(os.path.join(DATASET_BASE_DIR, 'train', '0'))\nrmtree(os.path.join(DATASET_BASE_DIR, 'val', '0'))\nrmtree(os.path.join(DATASET_BASE_DIR, 'stage_2_test_images'))","metadata":{"id":"HPB2TtXhziQQ","execution":{"iopub.status.busy":"2022-06-26T10:45:42.885514Z","iopub.execute_input":"2022-06-26T10:45:42.886378Z","iopub.status.idle":"2022-06-26T10:45:43.846984Z","shell.execute_reply.started":"2022-06-26T10:45:42.886340Z","shell.execute_reply":"2022-06-26T10:45:43.845986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Location to store images and mask\nUNET_DATA_DIR = os.path.join(DATASET_BASE_DIR, 'unet_data')","metadata":{"id":"ljtrpCXKrIWx","execution":{"iopub.status.busy":"2022-06-26T10:45:52.081210Z","iopub.execute_input":"2022-06-26T10:45:52.081601Z","iopub.status.idle":"2022-06-26T10:45:52.086365Z","shell.execute_reply.started":"2022-06-26T10:45:52.081569Z","shell.execute_reply":"2022-06-26T10:45:52.085358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.mkdir(UNET_DATA_DIR)\nos.chdir(UNET_DATA_DIR)\nsub_dir = ['train', 'test', 'val']","metadata":{"id":"45FeJ4dW2XaY","execution":{"iopub.status.busy":"2022-06-26T10:45:57.119123Z","iopub.execute_input":"2022-06-26T10:45:57.119803Z","iopub.status.idle":"2022-06-26T10:45:57.124887Z","shell.execute_reply.started":"2022-06-26T10:45:57.119763Z","shell.execute_reply":"2022-06-26T10:45:57.123422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for dir in sub_dir:\n  os.mkdir(dir)\n  os.chdir(dir)\n  os.mkdir('img')\n  os.mkdir('mask')\n\n  if dir == 'train':\n    ids = patientids_train\n  elif dir == 'val':\n    ids = patientids_val\n  else:\n    ids = patientids_test\n\n  for patient_id in tqdm.tqdm(ids):\n\n    rec = df[df['patientId'] == patient_id]\n\n    mask = np.zeros((1024, 1024))\n\n    for j, row in rec.iterrows():\n      if(row['Target'] == 0):\n        continue;\n\n      xmin = int(df.loc[j,'x'])\n      ymin = int(df.loc[j,'y'])\n      xmax = xmin + int(df.loc[j,'width'])\n      ymax = ymin + int(df.loc[j,'height'])\n      mask[ymin:ymax, xmin:xmax] = 255\n\n      copyfile(os.path.join(DATASET_BASE_DIR, dir, '1', patient_id) +'.png', os.path.join(UNET_DATA_DIR, dir, 'img', patient_id) +'.png')\n\n      # Save masks as png\n      cv2.imwrite(os.path.join(UNET_DATA_DIR, dir, 'mask', patient_id) +'.png', mask)\n\n  os.chdir('..')","metadata":{"id":"QYticLAy2kgm","outputId":"f4582a84-0a0f-4c75-e778-0355736d87ef","execution":{"iopub.status.busy":"2022-06-26T10:45:58.752123Z","iopub.execute_input":"2022-06-26T10:45:58.752778Z","iopub.status.idle":"2022-06-26T10:50:11.803639Z","shell.execute_reply.started":"2022-06-26T10:45:58.752744Z","shell.execute_reply":"2022-06-26T10:50:11.802781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Defining a function that returns the generator object usable by u-net model. It essentialy returns augmented(if enabled) image and corresponding mask.","metadata":{"id":"nYMWlkDT3nhN"}},{"cell_type":"code","source":"def unetGenerator(batch_size, train_path, image_folder, mask_folder, aug_dict, image_color_mode = \"grayscale\",\n                    mask_color_mode = \"grayscale\", num_class = 2, target_size = (IMG_HEIGHT, IMG_WIDTH), seed = 33):\n  '''\n  NOTE : Use the same seed for image_datagen and mask_datagen to ensure the transformation for image and mask is the same\n  '''\n  image_datagen = ImageDataGenerator(**aug_dict)\n\n  mask_datagen = ImageDataGenerator(**aug_dict)\n\n  image_generator = image_datagen.flow_from_directory(train_path,\n                                                      classes = [image_folder],\n                                                      class_mode = None,\n                                                      color_mode = image_color_mode,\n                                                      target_size = target_size,\n                                                      batch_size = batch_size,\n                                                      seed = seed)\n\n  mask_generator = mask_datagen.flow_from_directory(train_path,\n                                                    classes = [mask_folder],\n                                                    class_mode = None,\n                                                    color_mode = mask_color_mode,\n                                                    target_size = target_size,\n                                                    batch_size = batch_size,\n                                                    seed = seed)\n\n  combined_generator = zip(image_generator, mask_generator)\n  for (img,mask) in combined_generator:\n    # Normalize image and mask\n    img = img / 255\n    mask = mask /255\n    mask[mask > 0.5] = 1\n    mask[mask <= 0.5] = 0\n    yield (img,mask)","metadata":{"id":"VboHRQKT5YqB","execution":{"iopub.status.busy":"2022-06-26T10:50:15.557957Z","iopub.execute_input":"2022-06-26T10:50:15.558416Z","iopub.status.idle":"2022-06-26T10:50:15.573559Z","shell.execute_reply.started":"2022-06-26T10:50:15.558374Z","shell.execute_reply":"2022-06-26T10:50:15.571705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualizing the image and mask returned by the generator","metadata":{"id":"DR81Cy226Lt5"}},{"cell_type":"code","source":"data_gen_args = dict(rotation_range=0.2, width_shift_range=0.05, \n                     height_shift_range=0.05, shear_range=0.05, \n                     zoom_range=0.05, horizontal_flip=True, \n                     fill_mode='nearest')","metadata":{"id":"AE9K_4yE6Sw3","execution":{"iopub.status.busy":"2022-06-26T10:50:17.384346Z","iopub.execute_input":"2022-06-26T10:50:17.385046Z","iopub.status.idle":"2022-06-26T10:50:17.389297Z","shell.execute_reply.started":"2022-06-26T10:50:17.385008Z","shell.execute_reply":"2022-06-26T10:50:17.388493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dummyGenerator = unetGenerator(1, os.path.join(UNET_DATA_DIR, 'train'),\n                             'img','mask', data_gen_args, image_color_mode = \"rgb\")","metadata":{"id":"wIjDyppv6YLy","execution":{"iopub.status.busy":"2022-06-26T10:50:18.270889Z","iopub.execute_input":"2022-06-26T10:50:18.271858Z","iopub.status.idle":"2022-06-26T10:50:18.277248Z","shell.execute_reply.started":"2022-06-26T10:50:18.271811Z","shell.execute_reply":"2022-06-26T10:50:18.276266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(3):\n  img, mask = dummyGenerator.__next__()\n  fig, ax = plt.subplots(1, 2, figsize = (10, 8))\n  ax[0].imshow(img[0]);\n  ax[0].set_title('Image')\n  ax[1].imshow(np.squeeze(mask[0]), cmap = plt.cm.gray);\n  ax[1].set_title('Mask')\n  plt.show();","metadata":{"id":"dY8mZQ4v6vZP","outputId":"17d0f9c6-bdf9-4f1c-df3e-ed0df0405e8f","execution":{"iopub.status.busy":"2022-06-26T10:50:19.316100Z","iopub.execute_input":"2022-06-26T10:50:19.316779Z","iopub.status.idle":"2022-06-26T10:50:20.636167Z","shell.execute_reply.started":"2022-06-26T10:50:19.316739Z","shell.execute_reply":"2022-06-26T10:50:20.635367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create generator objects to be used during model training and testing","metadata":{"id":"STsrLamT70Hx"}},{"cell_type":"code","source":"unet_train_gen = unetGenerator(32, os.path.join(UNET_DATA_DIR, 'train'), 'img', 'mask', data_gen_args)\nunet_val_gen = unetGenerator(32, os.path.join(UNET_DATA_DIR, 'val'), 'img', 'mask', dict())\nunet_test_gen = unetGenerator(32, os.path.join(UNET_DATA_DIR, 'test'), 'img', 'mask', dict())","metadata":{"id":"uL5aqrTE76Rw","execution":{"iopub.status.busy":"2022-06-26T10:50:27.023833Z","iopub.execute_input":"2022-06-26T10:50:27.024767Z","iopub.status.idle":"2022-06-26T10:50:27.030223Z","shell.execute_reply.started":"2022-06-26T10:50:27.024729Z","shell.execute_reply":"2022-06-26T10:50:27.029269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Build a simple unet model","metadata":{"id":"ra67maxv8P-t"}},{"cell_type":"code","source":"def conv_block(input, num_filters):\n    x = tf.keras.layers.Conv2D(num_filters, 3, padding=\"same\")(input)\n    x = tf.keras.layers.BatchNormalization()(x)\n    x = tf.keras.layers.Activation(\"relu\")(x)\n\n    x = tf.keras.layers.Conv2D(num_filters, 3, padding=\"same\")(x)\n    x = tf.keras.layers.BatchNormalization()(x) \n    x = tf.keras.layers.Activation(\"relu\")(x)\n\n    return x\ndef encoder_block(input, num_filters):\n    x = conv_block(input, num_filters)\n    p = tf.keras.layers.MaxPool2D((2, 2))(x)\n    return x, p   \n\ndef decoder_block(input, skip_features, num_filters):\n    x = tf.keras.layers.Conv2DTranspose(num_filters, (2, 2), strides=2, padding=\"same\")(input)\n    x = tf.keras.layers.Concatenate()([x, skip_features])\n    x = conv_block(x, num_filters)\n    return x","metadata":{"id":"3BHaIZD_2yVN","execution":{"iopub.status.busy":"2022-06-26T10:50:31.224374Z","iopub.execute_input":"2022-06-26T10:50:31.225274Z","iopub.status.idle":"2022-06-26T10:50:31.235577Z","shell.execute_reply.started":"2022-06-26T10:50:31.225240Z","shell.execute_reply":"2022-06-26T10:50:31.233441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_unet(input_shape, n_classes):\n  inputs = tf.keras.layers.Input(input_shape)\n  \n  s1, p1 = encoder_block(inputs, 64)\n  s2, p2 = encoder_block(p1, 128)\n  s3, p3 = encoder_block(p2, 256)\n  s4, p4 = encoder_block(p3, 512)\n\n  b1 = conv_block(p4, 1024) #Bridge\n\n  d1 = decoder_block(b1, s4, 512)\n  d2 = decoder_block(d1, s3, 256)\n  d3 = decoder_block(d2, s2, 128)\n  d4 = decoder_block(d3, s1, 64)\n\n  outputs = tf.keras.layers.Conv2D(n_classes, 1, padding=\"same\", activation = 'sigmoid')(d4)\n\n  model = tf.keras.Model(inputs, outputs, name = \"U-Net\")\n\n  return model","metadata":{"id":"G8GOmH-T8TFz","execution":{"iopub.status.busy":"2022-06-26T10:50:32.543616Z","iopub.execute_input":"2022-06-26T10:50:32.544421Z","iopub.status.idle":"2022-06-26T10:50:32.552663Z","shell.execute_reply.started":"2022-06-26T10:50:32.544380Z","shell.execute_reply":"2022-06-26T10:50:32.551723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Define metric and loss function to be used for u-net model training","metadata":{"id":"SY1xHPVL8u4m"}},{"cell_type":"code","source":"smooth = 1e-15\ndef dice_coef(y_true, y_pred):\n    y_true = tf.keras.layers.Flatten()(y_true)\n    y_pred = tf.keras.layers.Flatten()(y_pred)\n    intersection = tf.reduce_sum(y_true * y_pred)\n    return (2. * intersection + smooth) / (tf.reduce_sum(y_true) + tf.reduce_sum(y_pred) + smooth)","metadata":{"id":"1sPliLHX8rac","execution":{"iopub.status.busy":"2022-06-26T10:50:35.013799Z","iopub.execute_input":"2022-06-26T10:50:35.014432Z","iopub.status.idle":"2022-06-26T10:50:35.020806Z","shell.execute_reply.started":"2022-06-26T10:50:35.014395Z","shell.execute_reply":"2022-06-26T10:50:35.019857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def loss(y_true, y_pred):\n    return tf.keras.losses.binary_crossentropy(y_true, y_pred) - tf.keras.backend.log(dice_coef(y_true, y_pred) + tf.keras.backend.epsilon())","metadata":{"id":"6RPpLRnX82eO","execution":{"iopub.status.busy":"2022-06-26T10:50:35.941746Z","iopub.execute_input":"2022-06-26T10:50:35.942101Z","iopub.status.idle":"2022-06-26T10:50:35.947398Z","shell.execute_reply.started":"2022-06-26T10:50:35.942071Z","shell.execute_reply":"2022-06-26T10:50:35.946522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#tf.keras.backend.clear_session()\ninput_shape = (IMG_HEIGHT, IMG_WIDTH, 1)\nmodel = build_unet(input_shape, n_classes=1)","metadata":{"id":"v94SGeOY9Ay1","execution":{"iopub.status.busy":"2022-06-26T10:50:37.804812Z","iopub.execute_input":"2022-06-26T10:50:37.805188Z","iopub.status.idle":"2022-06-26T10:50:38.197707Z","shell.execute_reply.started":"2022-06-26T10:50:37.805157Z","shell.execute_reply":"2022-06-26T10:50:38.196872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"id":"jeSNtPFr26nC","outputId":"feaab044-4aa1-4f54-93e0-32492410e308","execution":{"iopub.status.busy":"2022-06-26T10:50:39.593880Z","iopub.execute_input":"2022-06-26T10:50:39.594630Z","iopub.status.idle":"2022-06-26T10:50:39.609167Z","shell.execute_reply.started":"2022-06-26T10:50:39.594592Z","shell.execute_reply":"2022-06-26T10:50:39.608024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer='adam', loss=loss, metrics=['accuracy', dice_coef])","metadata":{"id":"Ly_nDSmG91s-","execution":{"iopub.status.busy":"2022-06-26T10:50:43.401236Z","iopub.execute_input":"2022-06-26T10:50:43.401893Z","iopub.status.idle":"2022-06-26T10:50:43.425041Z","shell.execute_reply.started":"2022-06-26T10:50:43.401844Z","shell.execute_reply":"2022-06-26T10:50:43.424094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Create Checkpoint","metadata":{"id":"IGH_q0QI9uol"}},{"cell_type":"code","source":"model_checkpoint = tf.keras.callbacks.ModelCheckpoint(os.path.join(DATASET_BASE_DIR,'rsna_simple_unet.h5'), save_best_only = True, \n                                                      monitor = 'val_dice_coef', mode='max', verbose = 1)","metadata":{"id":"6G1lwM349w3L","execution":{"iopub.status.busy":"2022-06-26T10:50:49.340888Z","iopub.execute_input":"2022-06-26T10:50:49.341266Z","iopub.status.idle":"2022-06-26T10:50:49.346645Z","shell.execute_reply.started":"2022-06-26T10:50:49.341236Z","shell.execute_reply":"2022-06-26T10:50:49.345219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Train model","metadata":{"id":"6pikNbDK95la"}},{"cell_type":"code","source":"history = model.fit(unet_train_gen, batch_size = 32,\n                    epochs = 10, validation_data = unet_val_gen, \n                    steps_per_epoch = 100, validation_steps = 30, callbacks = [model_checkpoint])","metadata":{"id":"6uqRLHiO948L","outputId":"b6ab1a35-6623-4d66-d5e6-965ca50b2a68","execution":{"iopub.status.busy":"2022-06-26T10:50:57.893462Z","iopub.execute_input":"2022-06-26T10:50:57.893942Z","iopub.status.idle":"2022-06-26T11:09:23.565907Z","shell.execute_reply.started":"2022-06-26T10:50:57.893907Z","shell.execute_reply":"2022-06-26T11:09:23.564897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_loss(history)","metadata":{"id":"ePlurdCi-PiU","outputId":"7a7820c6-849e-4c2e-8bf3-928e0a46b615","execution":{"iopub.status.busy":"2022-06-26T11:10:28.437425Z","iopub.execute_input":"2022-06-26T11:10:28.438605Z","iopub.status.idle":"2022-06-26T11:10:28.682606Z","shell.execute_reply.started":"2022-06-26T11:10:28.438544Z","shell.execute_reply":"2022-06-26T11:10:28.681785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Evaluate performace on test dataset","metadata":{"id":"TJj1ljmI-VtN"}},{"cell_type":"code","source":"# Load best model\nbest_model = tf.keras.models.load_model(os.path.join(DATASET_BASE_DIR,'rsna_simple_unet.h5'),custom_objects = {'loss': loss, 'dice_coef':dice_coef})","metadata":{"id":"HUdakSvF-bJt","execution":{"iopub.status.busy":"2022-06-26T11:10:34.917336Z","iopub.execute_input":"2022-06-26T11:10:34.918157Z","iopub.status.idle":"2022-06-26T11:10:37.516533Z","shell.execute_reply.started":"2022-06-26T11:10:34.918121Z","shell.execute_reply":"2022-06-26T11:10:37.515660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_model.evaluate(unet_test_gen, steps = 28)","metadata":{"id":"cmxc_TnM-q-e","execution":{"iopub.status.busy":"2022-06-26T11:10:37.518760Z","iopub.execute_input":"2022-06-26T11:10:37.519044Z","iopub.status.idle":"2022-06-26T11:10:59.205007Z","shell.execute_reply.started":"2022-06-26T11:10:37.519018Z","shell.execute_reply":"2022-06-26T11:10:59.203960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualize the predictions","metadata":{"id":"wBpHuigZ85SO"}},{"cell_type":"code","source":"#def rsna_get_xray(id):\n#  '''\n#  Function to return x-ray pixel data\n#  Inputs : \n#          id - Patient ID\n#  '''\n#  return cv2.imread(os.path.join(UNET_DATA_DIR, 'test', 'img', id) + '.png') #pydicom.read_file(os.path.join('', id)+'.png').pixel_array","metadata":{"execution":{"iopub.status.busy":"2022-06-25T14:15:46.331936Z","iopub.execute_input":"2022-06-25T14:15:46.332422Z","iopub.status.idle":"2022-06-25T14:15:46.338365Z","shell.execute_reply.started":"2022-06-25T14:15:46.332369Z","shell.execute_reply":"2022-06-25T14:15:46.337581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(5):\n  # Load test image\n  test_dir = os.path.join(UNET_DATA_DIR, 'test', 'img')\n  filename = random.choice(os.listdir(test_dir))\n  test_img = cv2.imread(os.path.join(test_dir, filename), cv2.IMREAD_GRAYSCALE)\n  test_img = cv2.resize(test_img , dsize = (IMG_WIDTH, IMG_HEIGHT))\n  test_img = test_img/255\n  test_img = test_img.reshape(1, IMG_WIDTH, IMG_HEIGHT,1)\n\n  # Predict mask\n  prediction = best_model.predict(test_img)\n  prediction = prediction.reshape(224,224,1)\n  prediction = (255 * (prediction>0.5))\n\n  # Visualize the results alongwith original image and patch\n  fig, ax = plt.subplots(1, 2, figsize = (10, 8))\n  ax[0].imshow(rsna_get_xray_with_bboxes(filename[:-4]), cmap = plt.cm.gray);\n  ax[0].set_title('Image + Actual Pneumonia Patch')\n  ax[1].imshow(prediction[:,:,0], cmap = plt.cm.gray);\n  ax[1].set_title('Predicted Pneumonia Patch')\n  plt.show();","metadata":{"id":"Kf5V6CK44RLO","outputId":"e2734da7-427c-42c6-c1e9-bd8695f9d1db","execution":{"iopub.status.busy":"2022-06-26T11:11:51.075323Z","iopub.execute_input":"2022-06-26T11:11:51.075690Z","iopub.status.idle":"2022-06-26T11:11:54.634185Z","shell.execute_reply.started":"2022-06-26T11:11:51.075661Z","shell.execute_reply":"2022-06-26T11:11:54.633341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We are getting dice coefficient of approximately 0.62 on test data with this model and the predicted pneumonia patches also look pretty good.","metadata":{}},{"cell_type":"markdown","source":"Next we'll build a Mobilenetv2 based U-net model","metadata":{"id":"8dAgz7tm-bOT"}},{"cell_type":"code","source":"def build_mobilenet_unet():\n    inputs = tf.keras.layers.Input(shape=(IMG_HEIGHT, IMG_WIDTH, 3), name=\"input_image\")\n    \n    # Load mobilenetv2\n    encoder = tf.keras.applications.MobileNetV2(input_tensor=inputs, weights=\"imagenet\", include_top=False, alpha=0.35)\n    encoder.trainable = False\n    \n    # Init decoder. It starts from output of encoder.\n    decoder = encoder.get_layer(\"block_13_expand_relu\").output\n    \n    # Upsample\n    decoder = tf.keras.layers.UpSampling2D()(decoder)\n    \n    # Concatenate with encoder's block 6 output(skip connection)\n    decoder = tf.keras.layers.Concatenate()([decoder, encoder.get_layer('block_6_expand_relu').output])\n    \n    # Add 2 layers of convolution\n    decoder = tf.keras.layers.Conv2D(64, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n        \n    decoder = tf.keras.layers.Conv2D(64, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n    \n    # Upsample\n    decoder = tf.keras.layers.UpSampling2D()(decoder)\n    \n    # Concatenate with encoder's block 3 output(skip connection)\n    decoder = tf.keras.layers.Concatenate()([decoder, encoder.get_layer('block_3_expand_relu').output])\n    \n    # Add 2 layers of convolution\n    decoder = tf.keras.layers.Conv2D(48, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n        \n    decoder = tf.keras.layers.Conv2D(48, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n    \n    # Upsample\n    decoder = tf.keras.layers.UpSampling2D()(decoder)\n    \n    # Concatenate with encoder's block 1 output(skip connection)\n    decoder = tf.keras.layers.Concatenate()([decoder, encoder.get_layer('block_1_expand_relu').output])\n    \n    # Add 2 layers of convolution\n    decoder = tf.keras.layers.Conv2D(32, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n        \n    decoder = tf.keras.layers.Conv2D(32, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n    \n    # Upsample\n    decoder = tf.keras.layers.UpSampling2D()(decoder)\n    \n    # Concatenate with input_image(skip connection)\n    decoder = tf.keras.layers.Concatenate()([decoder, encoder.get_layer('input_image').output])\n    \n    # Add 2 layers of convolution\n    decoder = tf.keras.layers.Conv2D(16, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n        \n    decoder = tf.keras.layers.Conv2D(16, (3, 3), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.BatchNormalization()(decoder)\n    decoder = tf.keras.layers.Activation(\"relu\")(decoder)\n        \n    decoder = tf.keras.layers.Conv2D(1, (1, 1), padding=\"same\")(decoder)\n    decoder = tf.keras.layers.Activation(\"sigmoid\")(decoder)\n    \n    model = tf.keras.models.Model(inputs, decoder)\n    return model","metadata":{"id":"08pB_OYW6pv2","execution":{"iopub.status.busy":"2022-06-26T11:11:58.094597Z","iopub.execute_input":"2022-06-26T11:11:58.095305Z","iopub.status.idle":"2022-06-26T11:11:58.118664Z","shell.execute_reply.started":"2022-06-26T11:11:58.095268Z","shell.execute_reply":"2022-06-26T11:11:58.117654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unet_train_gen = unetGenerator(32, os.path.join(UNET_DATA_DIR, 'train'),'img','mask', data_gen_args, image_color_mode = \"rgb\")\nunet_val_gen = unetGenerator(32, os.path.join(UNET_DATA_DIR, 'val'),'img','mask', dict(), image_color_mode = \"rgb\")\nunet_test_gen = unetGenerator(32, os.path.join(UNET_DATA_DIR, 'test'), 'img', 'mask', dict(), image_color_mode = \"rgb\")","metadata":{"id":"M78D7RQn7Fx5","execution":{"iopub.status.busy":"2022-06-26T11:11:59.332156Z","iopub.execute_input":"2022-06-26T11:11:59.332855Z","iopub.status.idle":"2022-06-26T11:11:59.338958Z","shell.execute_reply.started":"2022-06-26T11:11:59.332817Z","shell.execute_reply":"2022-06-26T11:11:59.337781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mobilenet_unet_model = build_mobilenet_unet()","metadata":{"id":"f9Mo6RyP5-oB","execution":{"iopub.status.busy":"2022-06-26T11:12:00.695444Z","iopub.execute_input":"2022-06-26T11:12:00.696568Z","iopub.status.idle":"2022-06-26T11:12:01.966719Z","shell.execute_reply.started":"2022-06-26T11:12:00.696513Z","shell.execute_reply":"2022-06-26T11:12:01.965685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mobilenet_unet_model.compile(loss = loss, optimizer = 'adam', metrics = [dice_coef])","metadata":{"id":"GPB-os8qBJPA","execution":{"iopub.status.busy":"2022-06-26T11:12:01.968275Z","iopub.execute_input":"2022-06-26T11:12:01.968710Z","iopub.status.idle":"2022-06-26T11:12:01.983250Z","shell.execute_reply.started":"2022-06-26T11:12:01.968676Z","shell.execute_reply":"2022-06-26T11:12:01.982219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_checkpoint = tf.keras.callbacks.ModelCheckpoint(os.path.join(DATASET_BASE_DIR,'rsna_mobilenet_unet.h5'), save_best_only = True, \n                                                      monitor = 'val_dice_coef', mode = 'max', verbose = 1)","metadata":{"id":"e4FeGBaSBJRc","execution":{"iopub.status.busy":"2022-06-26T11:12:03.155371Z","iopub.execute_input":"2022-06-26T11:12:03.156072Z","iopub.status.idle":"2022-06-26T11:12:03.161557Z","shell.execute_reply.started":"2022-06-26T11:12:03.156033Z","shell.execute_reply":"2022-06-26T11:12:03.160294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = mobilenet_unet_model.fit(unet_train_gen, epochs = 20, batch_size = 32,  \n                 validation_data=unet_val_gen, callbacks = [model_checkpoint], steps_per_epoch = 100, validation_steps = 30)","metadata":{"id":"CvNARqLPBJbC","execution":{"iopub.status.busy":"2022-06-26T11:12:05.104460Z","iopub.execute_input":"2022-06-26T11:12:05.105091Z","iopub.status.idle":"2022-06-26T11:48:31.100759Z","shell.execute_reply.started":"2022-06-26T11:12:05.105053Z","shell.execute_reply":"2022-06-26T11:48:31.099831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_loss(history)","metadata":{"id":"Sc6yt6N1B61d","execution":{"iopub.status.busy":"2022-06-26T11:48:31.103502Z","iopub.execute_input":"2022-06-26T11:48:31.103897Z","iopub.status.idle":"2022-06-26T11:48:31.325090Z","shell.execute_reply.started":"2022-06-26T11:48:31.103860Z","shell.execute_reply":"2022-06-26T11:48:31.324345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Evaluate performance on test data","metadata":{"id":"4AXwZ2_gCAdi"}},{"cell_type":"code","source":"# Load best model\nbest_model = tf.keras.models.load_model(os.path.join(DATASET_BASE_DIR,'rsna_mobilenet_unet.h5'), custom_objects = {'loss': loss, 'dice_coef':dice_coef})","metadata":{"id":"_TA7cSNXB9Ii","execution":{"iopub.status.busy":"2022-06-26T11:48:35.811774Z","iopub.execute_input":"2022-06-26T11:48:35.812152Z","iopub.status.idle":"2022-06-26T11:48:37.394938Z","shell.execute_reply.started":"2022-06-26T11:48:35.812122Z","shell.execute_reply":"2022-06-26T11:48:37.393882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"best_model.evaluate(unet_test_gen, steps = 28)","metadata":{"id":"ljsgnPs-CGdz","execution":{"iopub.status.busy":"2022-06-26T11:48:37.673428Z","iopub.execute_input":"2022-06-26T11:48:37.674123Z","iopub.status.idle":"2022-06-26T11:48:59.963507Z","shell.execute_reply.started":"2022-06-26T11:48:37.674087Z","shell.execute_reply":"2022-06-26T11:48:59.962410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Visualize the predictions","metadata":{"id":"VN-6rExRCP1L"}},{"cell_type":"code","source":"test_dir = os.path.join(UNET_DATA_DIR, 'test', 'img')\ntest_dir_files = os.listdir(test_dir)\nfor i in range(5):\n  # Load test image\n  filename = random.choice(test_dir_files)\n  test_img = cv2.imread(os.path.join(test_dir, filename))\n  test_img = cv2.resize(test_img , dsize = (IMG_WIDTH, IMG_HEIGHT))\n  test_img = test_img/255\n  test_img = test_img.reshape(1, IMG_WIDTH, IMG_HEIGHT, 3)\n\n  # Predict mask\n  prediction = best_model.predict(test_img)\n  prediction = prediction.reshape(224,224,1)\n  prediction = (255 * (prediction>0.5))\n\n  # Visualize the results alongwith original image and patch\n  fig, ax = plt.subplots(1, 2, figsize = (10, 8))\n  ax[0].imshow(rsna_get_xray_with_bboxes(filename[:-4]), cmap = plt.cm.gray);\n  ax[0].set_title('Image + Actual Pneumonia Patch')\n  ax[1].imshow(prediction[:,:,0], cmap = plt.cm.gray);\n  ax[1].set_title('Predicted Pneumonia Patch')\n  plt.show();","metadata":{"id":"Up79HyTmCKmt","outputId":"018e7f83-2d41-4078-acea-19de75455592","execution":{"iopub.status.busy":"2022-06-26T11:49:08.631891Z","iopub.execute_input":"2022-06-26T11:49:08.632270Z","iopub.status.idle":"2022-06-26T11:49:12.252141Z","shell.execute_reply.started":"2022-06-26T11:49:08.632239Z","shell.execute_reply":"2022-06-26T11:49:12.251275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"With mobilenet based u-net model, the dice coefficient has improved further to approximately 0.65. We'll use this model for our integrated model.","metadata":{"id":"r0I0MEREwUFT"}},{"cell_type":"markdown","source":"<b> Create a single function to classify and detect pneumonia patches </b>","metadata":{"id":"FmIEU5eewYCE"}},{"cell_type":"code","source":"#!cp ../train_undersampled/rsna_predict_mobilenet_undersampled.h5 ./","metadata":{"execution":{"iopub.status.busy":"2022-06-25T14:42:12.044574Z","iopub.execute_input":"2022-06-25T14:42:12.045029Z","iopub.status.idle":"2022-06-25T14:42:12.832902Z","shell.execute_reply.started":"2022-06-25T14:42:12.044984Z","shell.execute_reply":"2022-06-25T14:42:12.831652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!ls","metadata":{"execution":{"iopub.status.busy":"2022-06-25T14:42:15.536631Z","iopub.execute_input":"2022-06-25T14:42:15.537013Z","iopub.status.idle":"2022-06-25T14:42:16.450512Z","shell.execute_reply.started":"2022-06-25T14:42:15.536981Z","shell.execute_reply":"2022-06-25T14:42:16.449405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load the best classification and segmentation models","metadata":{}},{"cell_type":"code","source":"clf_model = tf.keras.models.load_model(os.path.join(DATASET_BASE_DIR,'rsna_predict_mobilenet_undersampled.h5'))\npatch_detection_model = tf.keras.models.load_model(os.path.join(DATASET_BASE_DIR,'rsna_mobilenet_unet.h5'), custom_objects = {'loss': loss, 'dice_coef':dice_coef})","metadata":{"execution":{"iopub.status.busy":"2022-06-26T11:49:22.080991Z","iopub.execute_input":"2022-06-26T11:49:22.081373Z","iopub.status.idle":"2022-06-26T11:49:24.817720Z","shell.execute_reply.started":"2022-06-26T11:49:22.081340Z","shell.execute_reply":"2022-06-26T11:49:24.816665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predic_pneumonia(img):\n  # Resize, scale and reshape image\n  ip_img = cv2.resize(img , dsize = (IMG_WIDTH, IMG_HEIGHT))\n  ip_img = ip_img/255\n  ip_img = ip_img.reshape(1, IMG_WIDTH, IMG_HEIGHT, 3)\n\n  # Predict whether patient has pneumonia\n  clf_prediction = clf_model.predict(ip_img)\n\n  # Compare results with threshold\n  if(clf_prediction > 0.35):\n    mask = best_model.predict(ip_img)\n    mask = mask.reshape(224,224,1)\n    mask = (255 * (mask > 0.5))\n    return (True, mask)\n  else:\n    return (False, np.zeros((IMG_HEIGHT, IMG_WIDTH)))","metadata":{"id":"l5R5QReGrIZi","execution":{"iopub.status.busy":"2022-06-26T11:49:29.376945Z","iopub.execute_input":"2022-06-26T11:49:29.377334Z","iopub.status.idle":"2022-06-26T11:49:29.384608Z","shell.execute_reply.started":"2022-06-26T11:49:29.377301Z","shell.execute_reply":"2022-06-26T11:49:29.383650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Run the model on some of the images from test dataset","metadata":{"id":"w7SLoH7NKcXq"}},{"cell_type":"markdown","source":"Steps :-\n- Randomly take an image from test dataset.\n- Open image\n- Pass image to prediction function\n- Get results\n- Get ground reality\n- Display image, ground truth, prediction and mask","metadata":{"id":"1DgjqODnKmTD"}},{"cell_type":"code","source":"test_dir_class_0 = os.path.join(DATASET_BASE_DIR, 'test', '0')\ntest_dir_class_1 = os.path.join(DATASET_BASE_DIR, 'test', '1')\n\ntest_dir_class_0_files = os.listdir(test_dir_class_0)\ntest_dir_class_1_files = os.listdir(test_dir_class_1)\n\nfor i in range(10):\n  if(i < 5):\n    file_dir = test_dir_class_0\n    actual = 0\n    filename = random.choice(test_dir_class_0_files)\n  else:\n    file_dir = test_dir_class_1\n    actual = 1\n    filename = random.choice(test_dir_class_1_files)\n\n  test_img = cv2.imread(os.path.join(file_dir, filename))\n\n  img_class, mask = predic_pneumonia(test_img)\n\n  print(f'Actual : {actual}')\n  print(f'Prediction : {img_class}')\n\n  mask = mask.reshape(IMG_HEIGHT, IMG_WIDTH, 1)\n  mask = (255 * (mask > 0.5))\n\n  fig, ax = plt.subplots(1, 2, figsize = (10, 8))\n  ax[0].imshow(rsna_get_xray_with_bboxes(filename[:-4]), cmap = plt.cm.gray);\n  ax[0].set_title('Image + Actual Pneumonia Patch')\n  ax[1].imshow(mask[:,:,0], cmap = plt.cm.gray);\n  ax[1].set_title('Predicted Pneumonia Patch')\n  plt.show();","metadata":{"id":"Rn0a_58JrIcm","execution":{"iopub.status.busy":"2022-06-26T11:49:31.996380Z","iopub.execute_input":"2022-06-26T11:49:31.997191Z","iopub.status.idle":"2022-06-26T11:49:38.401519Z","shell.execute_reply.started":"2022-06-26T11:49:31.997154Z","shell.execute_reply":"2022-06-26T11:49:38.400690Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working/\n!tar -czf train_undersampled.tar.gz rsna-pneumonia-detection-challenge/train_undersampled\n\nfrom IPython.display import FileLink\n\nFileLink(r'train_undersampled.tar.gz')","metadata":{"execution":{"iopub.status.busy":"2022-06-25T15:53:02.32056Z","iopub.execute_input":"2022-06-25T15:53:02.320966Z","iopub.status.idle":"2022-06-25T15:55:29.014391Z","shell.execute_reply.started":"2022-06-25T15:53:02.32093Z","shell.execute_reply":"2022-06-25T15:55:29.013148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rsna_get_xray(id):\n  '''\n  Function to return x-ray pixel data\n  Inputs : \n          id - Patient ID\n  '''\n  #cv2.imread(os.path.join(UNET_DATA_DIR, 'test', 'img', id) + '.png') \n  return pydicom.read_file(os.path.join(TRAIN_IMAGES_BASE_PATH, id)+'.dcm').pixel_array","metadata":{"id":"owSxUoOXrIfO","execution":{"iopub.status.busy":"2022-06-25T14:58:36.861054Z","iopub.execute_input":"2022-06-25T14:58:36.861825Z","iopub.status.idle":"2022-06-25T14:58:36.866925Z","shell.execute_reply.started":"2022-06-25T14:58:36.861789Z","shell.execute_reply":"2022-06-25T14:58:36.865763Z"},"trusted":true},"execution_count":null,"outputs":[]}]}