{"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":"code","source":"import os\nimport glob\nfrom tqdm import tqdm_notebook as tqdm\nimport random \nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F\nfrom torchvision import transforms, utils\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport cv2\nfrom sklearn.metrics import classification_report, accuracy_score, roc_auc_score, confusion_matrix\nfrom sklearn.linear_model import LogisticRegression\nimport pickle\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nimport sys\nsys.path.append('../input/monai-v060-deep-learning-in-healthcare-imaging/')\nfrom monai.networks.nets import DenseNet121, DenseNet264\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-09-04T18:33:20.582635Z","iopub.execute_input":"2021-09-04T18:33:20.583022Z","iopub.status.idle":"2021-09-04T18:33:27.017539Z","shell.execute_reply.started":"2021-09-04T18:33:20.582942Z","shell.execute_reply":"2021-09-04T18:33:27.016616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification'","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:27.020848Z","iopub.execute_input":"2021-09-04T18:33:27.021109Z","iopub.status.idle":"2021-09-04T18:33:27.026562Z","shell.execute_reply.started":"2021-09-04T18:33:27.021082Z","shell.execute_reply":"2021-09-04T18:33:27.025654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_size = 256\nstack_size = 64\n\ndef dicom2array(path, voi_lut=True, fix_monochrome=True):\n    dicom = pydicom.read_file(path)\n    # VOI LUT (if available by DICOM device) is used to\n    # transform raw DICOM data to \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n    # depending on this value, X-ray may look inverted - fix that:\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    \n    data = data - np.min(data)\n    data = data / (np.max(data) if np.max(data)>0 else 1)\n    # data = (data * 255).astype(np.uint8)\n    # data = data/255.\n    data = cv2.resize(data, (img_size, img_size))\n    return data\n\ndef load_sequence(paths):\n    stack = []\n    # load only non zero slices\n    for i, path in  enumerate(paths):\n        data = dicom2array(path)\n        if data.max() == 0:\n            continue\n        else:\n            stack.append(data)\n    \n    # if all empty (present in some cases)\n    if len(stack)==0:\n        return np.zeros((img_size,img_size,stack_size))\n    \n    stack = np.dstack(stack)# [:,:,2:-2] # Skip first and last 2 slices (generally very small regions/ almost all black)\n    # skip slices(take every nth slice)\n    n = stack.shape[2]//stack_size + 1\n    start = np.random.choice([i for i in range(n)]) # select a random starting slice from first n slices\n    stack = stack[:,:,start::n]\n    # If sequence is very small, repeat it multiple times.\n    num_of_repetitions = stack_size//stack.shape[2]\n    stack = np.concatenate((stack,)*num_of_repetitions + (stack[:,:,:stack_size-stack.shape[2]*num_of_repetitions],), axis=2)\n    \n    return stack\n\ndef load_3d_dicom_images(scan_id, split = \"train\"):\n    \"\"\"\n    we will use some heuristics to choose the slices to avoid any numpy zero matrix (if possible)\n    \"\"\"\n    # Flair\n    flair = sorted(glob.glob(f\"{path}/{split}/{scan_id}/FLAIR/*.dcm\"), key=lambda x: int(x.split('/')[-1].split('-')[-1].split('.')[0]))\n    flair_img = load_sequence(flair)\n    \n    # T1W\n    t1w = sorted(glob.glob(f\"{path}/{split}/{scan_id}/T1w/*.dcm\"), key=lambda x: int(x.split('/')[-1].split('-')[-1].split('.')[0]))\n    t1w_img = load_sequence(t1w)\n    \n    # T1WCE\n    t1wce = sorted(glob.glob(f\"{path}/{split}/{scan_id}/T1wCE/*.dcm\"), key=lambda x: int(x.split('/')[-1].split('-')[-1].split('.')[0]))\n    t1wce_img = load_sequence(t1wce)\n    \n    # T2W\n    t2w = sorted(glob.glob(f\"{path}/{split}/{scan_id}/T2w/*.dcm\"), key=lambda x: int(x.split('/')[-1].split('-')[-1].split('.')[0]))\n    t2w_img = load_sequence(t2w)\n\n    return np.concatenate((flair_img, t1w_img, t1wce_img, t2w_img), axis = -1)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:27.028077Z","iopub.execute_input":"2021-09-04T18:33:27.028448Z","iopub.status.idle":"2021-09-04T18:33:27.046200Z","shell.execute_reply.started":"2021-09-04T18:33:27.028408Z","shell.execute_reply":"2021-09-04T18:33:27.045051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# let's write a simple pytorch dataloader\n\n\nclass BrainTumor(Dataset):\n    def __init__(self, df, path = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification', split = \"train\", validation_fold = 0):\n        \n        df.BraTS21ID = df.BraTS21ID.apply(lambda x: str(x).zfill(5))\n        self.labels = {}            \n        if split == \"val\":\n            self.split = 'train'\n            val_data = df[df.kfold==validation_fold]\n            brats = list(val_data[\"BraTS21ID\"])\n            mgmt = list(val_data[\"MGMT_value\"])\n            for b, m in zip(brats, mgmt):\n                self.labels[b] = m\n            \n            self.ids = [a.split(\"/\")[-1] for a in sorted(glob.glob(path + f\"/{self.split}/\" + \"/*\"))]\n            self.ids = [id for id in self.ids if id in val_data.BraTS21ID.values]\n        elif split == \"train\":\n            self.split = split\n            train_data = df[df.kfold!=validation_fold]\n            brats = list(train_data[\"BraTS21ID\"])\n            mgmt = list(train_data[\"MGMT_value\"])\n            for b, m in zip(brats, mgmt):\n                self.labels[b] = m\n            \n            self.ids = [a.split(\"/\")[-1] for a in sorted(glob.glob(path + f\"/{self.split}/\" + \"/*\"))]\n            self.ids = [id for id in self.ids if id in train_data.BraTS21ID.values]\n        else:\n            self.split = split\n            self.ids = [a.split(\"/\")[-1] for a in sorted(glob.glob(path + f\"/{self.split}/\" + \"/*\"))]\n            \n    \n    def __len__(self):\n        return len(self.ids)\n    \n    def get_transforms(self):\n        return A.Compose([\n#                     A.OneOf([\n#                         A.RandomBrightnessContrast (brightness_limit=0.1, contrast_limit=0.1, brightness_by_max=False),\n#                         A.IAAAffine (shear=(-15,15), scale=(0.85,1.15), translate_percent=(0,0.15),rotate=(-25,25), mode='reflect'),\n#                         A.GaussianBlur(blur_limit=(3,7)),\n#                     ], p=0.5),\n                    ToTensorV2()\n                ])\n    \n    def __getitem__(self, idx):\n        imgs = load_3d_dicom_images(self.ids[idx], self.split)\n        transform = self.get_transforms()\n        augments = transform(image=imgs)\n        imgs = augments['image']\n        imgs = torch.stack([imgs[:stack_size,:,:],imgs[stack_size:stack_size*2,:,:],imgs[stack_size*2:stack_size*3,:,:],imgs[stack_size*3:,:,:]], axis=0)\n        \n        if self.split != \"test\":\n            label = self.labels[self.ids[idx]]\n            return torch.tensor(imgs, dtype = torch.float32), torch.tensor(label, dtype = torch.float32)\n        else:\n            return torch.tensor(imgs, dtype = torch.float32)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:27.047833Z","iopub.execute_input":"2021-09-04T18:33:27.048207Z","iopub.status.idle":"2021-09-04T18:33:27.066218Z","shell.execute_reply.started":"2021-09-04T18:33:27.048173Z","shell.execute_reply":"2021-09-04T18:33:27.065405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/sample_submission.csv\")\n\ntest_dataset = BrainTumor(submission, split='test')\ntest_loader = DataLoader(test_dataset, batch_size=4, shuffle=False, num_workers=4, pin_memory=True)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:27.069308Z","iopub.execute_input":"2021-09-04T18:33:27.069610Z","iopub.status.idle":"2021-09-04T18:33:27.097693Z","shell.execute_reply.started":"2021-09-04T18:33:27.069586Z","shell.execute_reply":"2021-09-04T18:33:27.096907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gpu = torch.device(f\"cuda:0\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:27.100132Z","iopub.execute_input":"2021-09-04T18:33:27.100412Z","iopub.status.idle":"2021-09-04T18:33:27.152863Z","shell.execute_reply.started":"2021-09-04T18:33:27.100388Z","shell.execute_reply":"2021-09-04T18:33:27.151915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_flair = torch.load('../input/miccai-densenet-264/densenet-264-flair-fold-0.pt', map_location=gpu)\nmodel_flair.eval()\nmodel_flair = model_flair.to(gpu)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:27.849231Z","iopub.execute_input":"2021-09-04T18:33:27.849570Z","iopub.status.idle":"2021-09-04T18:33:34.352320Z","shell.execute_reply.started":"2021-09-04T18:33:27.849542Z","shell.execute_reply":"2021-09-04T18:33:34.351386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_t1w = torch.load('../input/miccai-densenet-264/densenet-264-t1w-fold-1.pt', map_location=gpu)\nmodel_t1w.eval()\nmodel_t1w = model_t1w.to(gpu)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:34.353829Z","iopub.execute_input":"2021-09-04T18:33:34.354195Z","iopub.status.idle":"2021-09-04T18:33:35.812383Z","shell.execute_reply.started":"2021-09-04T18:33:34.354155Z","shell.execute_reply":"2021-09-04T18:33:35.811482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_t1wce = torch.load('../input/miccai-densenet-264/densenet-264-t1wce-fold-2.pt', map_location=gpu) \nmodel_t1wce.eval()\nmodel_t1wce = model_t1wce.to(gpu)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:35.814080Z","iopub.execute_input":"2021-09-04T18:33:35.814448Z","iopub.status.idle":"2021-09-04T18:33:36.817765Z","shell.execute_reply.started":"2021-09-04T18:33:35.814421Z","shell.execute_reply":"2021-09-04T18:33:36.816824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_t2w = torch.load('../input/miccai-densenet-264/densenet-264-t2w-fold-3.pt', map_location=gpu)\nmodel_t2w.eval()\nmodel_t2w = model_t2w.to(gpu)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:36.819335Z","iopub.execute_input":"2021-09-04T18:33:36.819682Z","iopub.status.idle":"2021-09-04T18:33:37.812008Z","shell.execute_reply.started":"2021-09-04T18:33:36.819645Z","shell.execute_reply":"2021-09-04T18:33:37.811201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Starting Predictions...')","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:37.813350Z","iopub.execute_input":"2021-09-04T18:33:37.813681Z","iopub.status.idle":"2021-09-04T18:33:37.821165Z","shell.execute_reply.started":"2021-09-04T18:33:37.813647Z","shell.execute_reply":"2021-09-04T18:33:37.819968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = []\nwith torch.no_grad():\n    for i, x  in tqdm(enumerate(test_loader), total=len(test_loader)):\n        x = x.to(gpu)\n        out = []\n        \n        # Get predictions from all 4 models.\n        # Here I have extracted separate channels from the input tensor for different sequence models, all for combined.\n        out.append(model_flair(torch.unsqueeze(x[:,0,...],1)).cpu().detach().sigmoid().numpy().reshape(-1).tolist())\n        out.append(model_t1w(torch.unsqueeze(x[:,1,...],1)).cpu().detach().sigmoid().numpy().reshape(-1).tolist())\n        out.append(model_t1wce(torch.unsqueeze(x[:,2,...],1)).cpu().detach().sigmoid().numpy().reshape(-1).tolist())\n        out.append(model_t2w(torch.unsqueeze(x[:,3,...],1)).cpu().detach().sigmoid().numpy().reshape(-1).tolist())\n\n        # Change shape from (4, n) to (n, 4) so each row contains prediction from all 4 models. (n is batch size)\n        out = np.array(out)\n        out = out.transpose(1,0)\n\n        # extend results of each item in batch to y_pred.\n        y_pred.extend(out.tolist())\n        print(f'{(i+1)/len(test_loader)}%') # Print progress for while commiting.\n#         break\ny_pred = np.array(y_pred)\n# y_pred = y_pred.mean(axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:33:41.033870Z","iopub.execute_input":"2021-09-04T18:33:41.034223Z","iopub.status.idle":"2021-09-04T18:34:47.722044Z","shell.execute_reply.started":"2021-09-04T18:33:41.034189Z","shell.execute_reply":"2021-09-04T18:34:47.720971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# stacking_classifier = pickle.load(open('../input/miccai-densenet-264/LR_Stacking_Classifier_DenseNet_264.sav', 'rb'))\nstacking_classifier = pickle.load(open('../input/miccai-densenet-264/XGB_Stacking_Classifier.sav', 'rb'))\ny_pred_stacking_classifier = stacking_classifier.predict_proba(y_pred)[:,1]","metadata":{"execution":{"iopub.status.busy":"2021-09-04T18:34:56.094476Z","iopub.execute_input":"2021-09-04T18:34:56.094922Z","iopub.status.idle":"2021-09-04T18:34:56.351051Z","shell.execute_reply.started":"2021-09-04T18:34:56.094882Z","shell.execute_reply":"2021-09-04T18:34:56.343798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission['MGMT_value'] = y_pred\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}