{"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 sys \nimport json\nimport glob\nimport random\nimport re\nimport collections\nimport time\n\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport torch\nfrom torch import nn\nfrom torch.utils import data as torch_data\nfrom sklearn import model_selection as sk_model_selection\nfrom torch.nn import functional as torch_functional\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score","metadata":{"papermill":{"duration":1.048295,"end_time":"2021-07-14T20:26:46.309722","exception":false,"start_time":"2021-07-14T20:26:45.261427","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-08T19:41:14.750982Z","iopub.execute_input":"2021-10-08T19:41:14.751862Z","iopub.status.idle":"2021-10-08T19:41:17.951028Z","shell.execute_reply.started":"2021-10-08T19:41:14.751748Z","shell.execute_reply":"2021-10-08T19:41:17.949848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/monai-private/monai-0.7.0-202109240007-py3-none-any.whl","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:41:38.731420Z","iopub.execute_input":"2021-10-08T19:41:38.731834Z","iopub.status.idle":"2021-10-08T19:42:08.301770Z","shell.execute_reply.started":"2021-10-08T19:41:38.731803Z","shell.execute_reply":"2021-10-08T19:42:08.300354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from monai.networks.nets.resnet import ResNet, resnet34, resnet50, resnet101, resnet152, resnet200","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:08.306125Z","iopub.execute_input":"2021-10-08T19:42:08.306668Z","iopub.status.idle":"2021-10-08T19:42:16.345209Z","shell.execute_reply.started":"2021-10-08T19:42:08.306615Z","shell.execute_reply":"2021-10-08T19:42:16.343960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_directory = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification'\ninput_monaipath = \"/kaggle/input/monai-v060-deep-learning-in-healthcare-imaging/\"\nmonaipath = \"/kaggle/tmp/monai/\"","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:17.803826Z","iopub.execute_input":"2021-10-08T19:42:17.804221Z","iopub.status.idle":"2021-10-08T19:42:17.811517Z","shell.execute_reply.started":"2021-10-08T19:42:17.804163Z","shell.execute_reply":"2021-10-08T19:42:17.810387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\npaths_flair = [\n    \"../input/resnet50-weights/resnet34_fold0_best_loss_FLAIR_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold1_best_loss_FLAIR_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold2_best_loss_FLAIR_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold3_best_loss_FLAIR_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold4_best_loss_FLAIR_mri_type.pth\",\n]\n\npaths_t1w = [\n    \"../input/resnet50-weights/resnet34_fold0_best_loss_T1w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold1_best_loss_T1w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold2_best_loss_T1w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold3_best_loss_T1w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold4_best_loss_T1w_mri_type.pth\",\n]\n\npaths_t1wCE = [\n    \"../input/resnet50-weights/resnet34_fold0_best_loss_T1wCE_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold1_best_loss_T1wCE_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold2_best_loss_T1wCE_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold3_best_loss_T1wCE_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold4_best_loss_T1wCE_mri_type.pth\",\n]\n\npaths_t2w = [\n    \"../input/resnet50-weights/resnet34_fold0_best_loss_T2w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold1_best_loss_T2w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold2_best_loss_T2w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold3_best_loss_T2w_mri_type.pth\",\n    \"../input/resnet50-weights/resnet34_fold4_best_loss_T2w_mri_type.pth\",\n]","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:18.287534Z","iopub.execute_input":"2021-10-08T19:42:18.287969Z","iopub.status.idle":"2021-10-08T19:42:18.350608Z","shell.execute_reply.started":"2021-10-08T19:42:18.287937Z","shell.execute_reply":"2021-10-08T19:42:18.349359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p {monaipath}\n!cp -r {input_monaipath}/* {monaipath}","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:18.690409Z","iopub.execute_input":"2021-10-08T19:42:18.690763Z","iopub.status.idle":"2021-10-08T19:42:24.526403Z","shell.execute_reply.started":"2021-10-08T19:42:18.690718Z","shell.execute_reply":"2021-10-08T19:42:24.525015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mri_types = ['FLAIR']\nSIZE = 256\nNUM_IMAGES = 64\nBATCH_SIZE = 4\nN_EPOCHS = 16\nSEED = 12345\nLEARNING_RATE = 0.0005\nLR_DECAY = 0.9\n\nsys.path.append(monaipath)\n\nfrom monai.networks.nets.resnet import resnet34","metadata":{"lines_to_end_of_cell_marker":2,"lines_to_next_cell":2,"papermill":{"duration":0.05565,"end_time":"2021-07-14T20:26:46.486521","exception":false,"start_time":"2021-07-14T20:26:46.430871","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-08T19:42:24.528626Z","iopub.execute_input":"2021-10-08T19:42:24.529080Z","iopub.status.idle":"2021-10-08T19:42:24.538673Z","shell.execute_reply.started":"2021-10-08T19:42:24.529035Z","shell.execute_reply":"2021-10-08T19:42:24.537295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Functions to load images","metadata":{}},{"cell_type":"code","source":"def load_dicom_image(path, img_size=SIZE):\n    dicom = pydicom.read_file(path)\n    data = dicom.pixel_array\n    if np.min(data)==np.max(data):\n        data = np.zeros((img_size,img_size))\n        return data\n    \n    data = cv2.resize(data, (img_size, img_size))\n    return data\n\n\ndef natural_sort(l): \n    convert = lambda text: int(text) if text.isdigit() else text.lower()\n    alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]\n    return sorted(l, key=alphanum_key)\n\n\ndef load_dicom_images_3d(scan_id, num_imgs=NUM_IMAGES, img_size=SIZE, mri_type=\"FLAIR\", split=\"train\"):\n    files = natural_sort(glob.glob(f\"{data_directory}/{split}/{scan_id}/{mri_type}/*.dcm\"))\n    \n    every_nth = len(files) / num_imgs\n    indexes = [min(int(round(i*every_nth)), len(files)-1) for i in range(0,num_imgs)]\n    \n    files_to_load = [files[i] for i in indexes]\n    \n    img3d = np.stack([load_dicom_image(f) for f in files_to_load]).T \n    \n    img3d = img3d - np.min(img3d)\n    if np.max(img3d) != 0:\n        img3d = img3d / np.max(img3d)\n    \n    return np.expand_dims(img3d,0)\n\n\nload_dicom_images_3d(\"00000\", mri_type=mri_types[0]).shape","metadata":{"papermill":{"duration":0.035761,"end_time":"2021-07-14T20:26:46.726756","exception":false,"start_time":"2021-07-14T20:26:46.690995","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-08T19:42:24.542825Z","iopub.execute_input":"2021-10-08T19:42:24.543444Z","iopub.status.idle":"2021-10-08T19:42:25.307340Z","shell.execute_reply.started":"2021-10-08T19:42:24.543404Z","shell.execute_reply":"2021-10-08T19:42:25.306042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed):\n    random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True\n\nset_seed(SEED)","metadata":{"papermill":{"duration":0.668331,"end_time":"2021-07-14T20:27:48.114522","exception":false,"start_time":"2021-07-14T20:27:47.446191","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-08T19:42:25.309584Z","iopub.execute_input":"2021-10-08T19:42:25.310189Z","iopub.status.idle":"2021-10-08T19:42:25.321350Z","shell.execute_reply.started":"2021-10-08T19:42:25.310112Z","shell.execute_reply":"2021-10-08T19:42:25.320011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## train / test splits","metadata":{}},{"cell_type":"code","source":"samples_to_exclude = [109, 123, 709]\n\ntrain_df = pd.read_csv(f\"{data_directory}/train_labels.csv\")\nprint(\"original shape\", train_df.shape)\ntrain_df = train_df[~train_df.BraTS21ID.isin(samples_to_exclude)]\nprint(\"new shape\", train_df.shape)\ndisplay(train_df)\n\ndf_train, df_valid = sk_model_selection.train_test_split(\n    train_df, \n    test_size=0.2, \n    random_state=SEED, \n    stratify=train_df[\"MGMT_value\"],\n)\n","metadata":{"papermill":{"duration":0.633753,"end_time":"2021-07-14T20:27:49.350524","exception":false,"start_time":"2021-07-14T20:27:48.716771","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-08T19:42:25.323042Z","iopub.execute_input":"2021-10-08T19:42:25.323750Z","iopub.status.idle":"2021-10-08T19:42:25.376912Z","shell.execute_reply.started":"2021-10-08T19:42:25.323700Z","shell.execute_reply":"2021-10-08T19:42:25.375874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.tail()","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:25.378535Z","iopub.execute_input":"2021-10-08T19:42:25.379158Z","iopub.status.idle":"2021-10-08T19:42:25.392793Z","shell.execute_reply.started":"2021-10-08T19:42:25.379110Z","shell.execute_reply":"2021-10-08T19:42:25.391295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model and training classes","metadata":{}},{"cell_type":"code","source":"class Dataset(torch_data.Dataset):\n    def __init__(self, paths, targets=None, mri_type=None, split=\"train\"):\n        self.paths = paths\n        self.targets = targets\n        self.mri_type = mri_type\n        self.split = split\n          \n    def __len__(self):\n        return len(self.paths)\n    \n    def __getitem__(self, index):\n        scan_id = self.paths[index]\n        if self.targets is None:\n            data = load_dicom_images_3d(str(scan_id).zfill(5), mri_type=self.mri_type[index], split=self.split)\n        else:\n            data = load_dicom_images_3d(str(scan_id).zfill(5), mri_type=self.mri_type[index], split=\"train\")\n            \n        if self.targets is None:\n            return {\"X\": data, \"id\": scan_id}\n        else:\n            return {\"X\": data, \"y\": torch.tensor(self.targets[index], dtype=torch.float)}\n","metadata":{"papermill":{"duration":0.634322,"end_time":"2021-07-14T20:27:50.594701","exception":false,"start_time":"2021-07-14T20:27:49.960379","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-10-08T19:42:25.394626Z","iopub.execute_input":"2021-10-08T19:42:25.395358Z","iopub.status.idle":"2021-10-08T19:42:25.406335Z","shell.execute_reply.started":"2021-10-08T19:42:25.395314Z","shell.execute_reply":"2021-10-08T19:42:25.405022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model():\n    model = resnet34(spatial_dims=3, n_input_channels=1, num_classes=1)\n    return model    ","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:25.409717Z","iopub.execute_input":"2021-10-08T19:42:25.410614Z","iopub.status.idle":"2021-10-08T19:42:25.420244Z","shell.execute_reply.started":"2021-10-08T19:42:25.410569Z","shell.execute_reply":"2021-10-08T19:42:25.419124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prediction","metadata":{}},{"cell_type":"code","source":"def predict(path, df, mri_type, split):\n    print(\"Predict:\", path, mri_type, df.shape)\n    df.loc[:,\"MRI_Type\"] = mri_type\n    data_retriever = Dataset(\n        df.index.values, \n        mri_type=df[\"MRI_Type\"].values,\n        split=split\n    )\n\n    data_loader = torch_data.DataLoader(\n        data_retriever,\n        batch_size=4,\n        shuffle=False,\n        num_workers=8,\n    )\n   \n    model = build_model()\n    model.to(device)\n    \n    state_dict = torch.load(path, map_location=torch.device('cpu'))\n    model.load_state_dict(state_dict)\n    \n    model.eval()\n    \n    y_pred = []\n    ids = []\n\n    for e, batch in enumerate(data_loader,1):\n        print(f\"{e}/{len(data_loader)}\", end=\"\\r\")\n        with torch.no_grad():\n            tmp_pred = torch.sigmoid(model(torch.tensor(batch[\"X\"]).float().to(device)).squeeze(1)).cpu().numpy().squeeze()\n            if tmp_pred.size == 1:\n                y_pred.append(tmp_pred)\n            else:\n                y_pred.extend(tmp_pred.tolist())\n            ids.extend(batch[\"id\"].numpy().tolist())\n            \n    preddf = pd.DataFrame({\"BraTS21ID\": ids, \"MGMT_value\": y_pred}) \n    preddf = preddf.set_index(\"BraTS21ID\")\n    return preddf","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:25.422396Z","iopub.execute_input":"2021-10-08T19:42:25.422954Z","iopub.status.idle":"2021-10-08T19:42:25.436919Z","shell.execute_reply.started":"2021-10-08T19:42:25.422914Z","shell.execute_reply":"2021-10-08T19:42:25.435553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Submission**","metadata":{}},{"cell_type":"code","source":"submission_flair = pd.read_csv(f\"{data_directory}/sample_submission.csv\", index_col=\"BraTS21ID\")\n\nsubmission_flair[\"MGMT_value\"] = 0\nfor m in paths_flair:\n    print(m)\n    pred = predict(m, submission_flair, \"FLAIR\", split=\"test\")\n    submission_flair[\"MGMT_value\"] += pred[\"MGMT_value\"]\n\nsubmission_flair[\"MGMT_value\"] /= len(paths_flair)\nsubmission_flair.head()\n","metadata":{"execution":{"iopub.status.busy":"2021-10-08T19:42:25.438634Z","iopub.execute_input":"2021-10-08T19:42:25.439648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_t1w = pd.read_csv(f\"{data_directory}/sample_submission.csv\", index_col=\"BraTS21ID\")\n\nsubmission_t1w[\"MGMT_value\"] = 0\nfor m in paths_t1w:\n    print(m)\n    pred = predict(m, submission_t1w, \"T1w\", split=\"test\")\n    submission_t1w[\"MGMT_value\"] += pred[\"MGMT_value\"]\n\nsubmission_t1w[\"MGMT_value\"] /= len(paths_t1w)\nsubmission_t1w.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-06T18:52:34.782354Z","iopub.execute_input":"2021-10-06T18:52:34.782709Z","iopub.status.idle":"2021-10-06T18:54:44.974042Z","shell.execute_reply.started":"2021-10-06T18:52:34.782674Z","shell.execute_reply":"2021-10-06T18:54:44.972733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_t1wCE = pd.read_csv(f\"{data_directory}/sample_submission.csv\", index_col=\"BraTS21ID\")\n\nsubmission_t1wCE[\"MGMT_value\"] = 0\nfor m in paths_t1wCE:\n    print(m)\n    pred = predict(m, submission_t1wCE, \"T1wCE\", split=\"test\")\n    submission_t1wCE[\"MGMT_value\"] += pred[\"MGMT_value\"]\n\nsubmission_t1wCE[\"MGMT_value\"] /= len(paths_t1wCE)\nsubmission_t1wCE.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-06T18:54:44.976289Z","iopub.execute_input":"2021-10-06T18:54:44.976706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_t2w = pd.read_csv(f\"{data_directory}/sample_submission.csv\", index_col=\"BraTS21ID\")\n\nsubmission_t2w[\"MGMT_value\"] = 0\nfor m in paths_t2w:\n    print(m)\n    pred = predict(m, submission_t2w, \"T2w\", split=\"test\")\n    submission_t2w[\"MGMT_value\"] += pred[\"MGMT_value\"]\n\nsubmission_t2w[\"MGMT_value\"] /= len(paths_t2w)\nsubmission_t2w.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(f\"{data_directory}/sample_submission.csv\", index_col=\"BraTS21ID\")","metadata":{"execution":{"iopub.status.busy":"2021-10-06T18:58:01.996937Z","iopub.execute_input":"2021-10-06T18:58:01.997295Z","iopub.status.idle":"2021-10-06T18:58:02.02765Z","shell.execute_reply.started":"2021-10-06T18:58:01.997262Z","shell.execute_reply":"2021-10-06T18:58:02.026798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission['MGMT_value'] = 0\nsubmission['MGMT_value'] = (submission_flair['MGMT_value'] + submission_t1w[\"MGMT_value\"] + submission_t1wCE[\"MGMT_value\"] + submission_t2w[\"MGMT_value\"]) / 4.0\nsubmission[\"MGMT_value\"].to_csv(\"submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2021-10-06T18:58:07.486709Z","iopub.execute_input":"2021-10-06T18:58:07.487081Z","iopub.status.idle":"2021-10-06T18:58:07.508566Z","shell.execute_reply.started":"2021-10-06T18:58:07.487049Z","shell.execute_reply":"2021-10-06T18:58:07.507455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}