{"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 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\nimport torch.nn.functional as F\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:01.789484Z","iopub.execute_input":"2021-09-23T03:45:01.789803Z","iopub.status.idle":"2021-09-23T03:45:01.797060Z","shell.execute_reply.started":"2021-09-23T03:45:01.789769Z","shell.execute_reply":"2021-09-23T03:45:01.796446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if os.path.exists(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification\"):\n    data_directory = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\n    pytorch3dpath = \"../input/efficientnetpyttorch3d/EfficientNet-PyTorch-3D\"\nelse:\n    data_directory = '/media/roland/data/kaggle/rsna-miccai-brain-tumor-radiogenomic-classification'\n    pytorch3dpath = \"EfficientNet-PyTorch-3D\"\n    \nmri_types = ['FLAIR','T1w','T1wCE','T2w']\nSIZE = 256\nNUM_IMAGES = 64\n\nsys.path.append(pytorch3dpath)\nfrom efficientnet_pytorch_3d import EfficientNet3D","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:01.798443Z","iopub.execute_input":"2021-09-23T03:45:01.798852Z","iopub.status.idle":"2021-09-23T03:45:01.814681Z","shell.execute_reply.started":"2021-09-23T03:45:01.798788Z","shell.execute_reply":"2021-09-23T03:45:01.813807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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    data = data - np.min(data)\n    if np.max(data) != 0:\n        data = data / np.max(data)\n    \n    #data = (data * 255).astype(np.uint8)\n    data = cv2.resize(data, (img_size, img_size))\n    return data\n\ndef load_dicom_images_3d(scan_id, num_imgs=NUM_IMAGES, img_size=SIZE, mri_type=\"FLAIR\", split=\"train\"):\n\n    files = sorted(glob.glob(f\"{data_directory}/{split}/{scan_id}/{mri_type}/*.dcm\"))\n    \n    middle = len(files)//2\n    num_imgs2 = num_imgs//2\n    p1 = max(0, middle - num_imgs2)\n    p2 = min(len(files), middle + num_imgs2)\n    img3d = np.stack([load_dicom_image(f) for f in files[p1:p2]]).T \n    if img3d.shape[-1] < num_imgs:\n        n_zero = np.zeros((img_size, img_size, num_imgs - img3d.shape[-1]))\n        img3d = np.concatenate((img3d,  n_zero), axis = -1)\n            \n    return np.expand_dims(img3d,0)\n\nload_dicom_images_3d(\"00000\").shape","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:01.816502Z","iopub.execute_input":"2021-09-23T03:45:01.816734Z","iopub.status.idle":"2021-09-23T03:45:02.279380Z","shell.execute_reply.started":"2021-09-23T03:45:01.816704Z","shell.execute_reply":"2021-09-23T03:45:02.278489Z"},"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(42)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.280494Z","iopub.execute_input":"2021-09-23T03:45:02.280941Z","iopub.status.idle":"2021-09-23T03:45:02.286353Z","shell.execute_reply.started":"2021-09-23T03:45:02.280897Z","shell.execute_reply":"2021-09-23T03:45:02.285760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(f\"{data_directory}/train_labels.csv\")\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=42, \n    stratify=train_df[\"MGMT_value\"],\n)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.287690Z","iopub.execute_input":"2021-09-23T03:45:02.288013Z","iopub.status.idle":"2021-09-23T03:45:02.312976Z","shell.execute_reply.started":"2021-09-23T03:45:02.287978Z","shell.execute_reply":"2021-09-23T03:45:02.312085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset(torch_data.Dataset):\n    def __init__(self, paths, targets=None, mri_type=None, label_smoothing=0.01, split=\"train\"):\n        self.paths = paths\n        self.targets = targets\n        self.mri_type = mri_type\n        self.label_smoothing = label_smoothing\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\": torch.tensor(data).float(), \"id\": scan_id}\n        else:\n            y = torch.tensor(abs(self.targets[index]-self.label_smoothing), dtype=torch.float)\n            return {\"X\": torch.tensor(data).float(), \"y\": y}","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.314326Z","iopub.execute_input":"2021-09-23T03:45:02.314561Z","iopub.status.idle":"2021-09-23T03:45:02.323788Z","shell.execute_reply.started":"2021-09-23T03:45:02.314534Z","shell.execute_reply":"2021-09-23T03:45:02.322742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.net = EfficientNet3D.from_name(\"efficientnet-b0\", override_params={'num_classes': 2}, in_channels=1)\n        n_features = self.net._fc.in_features\n        self.net._fc = nn.Linear(in_features=n_features, out_features=1, bias=True)\n    \n    def forward(self, x):\n        out = self.net(x)\n        return out","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.325770Z","iopub.execute_input":"2021-09-23T03:45:02.326814Z","iopub.status.idle":"2021-09-23T03:45:02.335892Z","shell.execute_reply.started":"2021-09-23T03:45:02.326705Z","shell.execute_reply":"2021-09-23T03:45:02.334863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modelfiles = None\n\nif not modelfiles:\n    modelfiles = ['FLAIR-e3-loss0.694-auc0.351.pth', 'T1w-e7-loss0.685-auc0.555.pth', 'T1wCE-e6-loss0.683-auc0.633.pth', 'T2w-e8-loss0.658-auc0.677.pth']\n    print(modelfiles)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.337349Z","iopub.execute_input":"2021-09-23T03:45:02.338127Z","iopub.status.idle":"2021-09-23T03:45:02.348150Z","shell.execute_reply.started":"2021-09-23T03:45:02.338067Z","shell.execute_reply":"2021-09-23T03:45:02.347041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.350214Z","iopub.execute_input":"2021-09-23T03:45:02.350635Z","iopub.status.idle":"2021-09-23T03:45:02.359400Z","shell.execute_reply.started":"2021-09-23T03:45:02.350587Z","shell.execute_reply":"2021-09-23T03:45:02.358215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(modelfile, df, mri_type, split):\n    print(\"Predict:\", modelfile, 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 = Model()\n    model.to(device)\n    \n    checkpoint = torch.load(f'../input/efficientnet3d-with-one-mri-type-model-weights/{modelfile}')\n    model.load_state_dict(checkpoint[\"model_state_dict\"])\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(batch[\"X\"].to(device))).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-09-23T03:45:02.363545Z","iopub.execute_input":"2021-09-23T03:45:02.363906Z","iopub.status.idle":"2021-09-23T03:45:02.375412Z","shell.execute_reply.started":"2021-09-23T03:45:02.363872Z","shell.execute_reply":"2021-09-23T03:45:02.374378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport sys \nimport json\nimport glob\nimport random\nimport collections\nimport time\nimport re\nimport math\nimport numpy as np\nimport pandas as pd\nimport cv2\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\nfrom random import shuffle\nfrom sklearn import model_selection as sk_model_selection\n\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nimport tensorflow as tf","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.376861Z","iopub.execute_input":"2021-09-23T03:45:02.377327Z","iopub.status.idle":"2021-09-23T03:45:02.392925Z","shell.execute_reply.started":"2021-09-23T03:45:02.377288Z","shell.execute_reply":"2021-09-23T03:45:02.391733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_directory = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\npytorch3dpath = \"../input/efficientnetpyttorch3d/EfficientNet-PyTorch-3D\"\n \nmri_types = ['FLAIR','T1w','T1wCE','T2w']\nIMAGE_SIZE = 256\nNUM_IMAGES = 64","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.394092Z","iopub.execute_input":"2021-09-23T03:45:02.394643Z","iopub.status.idle":"2021-09-23T03:45:02.405745Z","shell.execute_reply.started":"2021-09-23T03:45:02.394605Z","shell.execute_reply":"2021-09-23T03:45:02.404756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission = pd.read_csv('../input/rsna-miccai-brain-tumor-radiogenomic-classification/sample_submission.csv')\ntest=sample_submission\ntest['BraTS21ID5'] = [format(x, '05d') for x in test.BraTS21ID]\ntest.head(3)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.407033Z","iopub.execute_input":"2021-09-23T03:45:02.407377Z","iopub.status.idle":"2021-09-23T03:45:02.430578Z","shell.execute_reply.started":"2021-09-23T03:45:02.407336Z","shell.execute_reply":"2021-09-23T03:45:02.429687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dicom_image(path, img_size=IMAGE_SIZE, voi_lut=True, rotate=0):\n    dicom = pydicom.read_file(path)\n    data = dicom.pixel_array\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n        \n    if rotate > 0:\n        rot_choices = [0, cv2.ROTATE_90_CLOCKWISE, cv2.ROTATE_90_COUNTERCLOCKWISE, cv2.ROTATE_180]\n        data = cv2.rotate(data, rot_choices[rotate])\n        \n    data = cv2.resize(data, (img_size, img_size))\n    return data\n\n\ndef load_dicom_images_3d(scan_id, num_imgs=NUM_IMAGES, img_size=IMAGE_SIZE, mri_type=\"FLAIR\", split=\"test\", rotate=0):\n\n    files = sorted(glob.glob(f\"{data_directory}/{split}/{scan_id}/{mri_type}/*.dcm\"), \n               key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])\n\n    middle = len(files)//2\n    num_imgs2 = num_imgs//2\n    p1 = max(0, middle - num_imgs2)\n    p2 = min(len(files), middle + num_imgs2)\n    img3d = np.stack([load_dicom_image(f, rotate=rotate) for f in files[p1:p2]]).T \n    if img3d.shape[-1] < num_imgs:\n        n_zero = np.zeros((img_size, img_size, num_imgs - img3d.shape[-1]))\n        img3d = np.concatenate((img3d,  n_zero), axis = -1)\n        \n    if np.min(img3d) < np.max(img3d):\n        img3d = img3d - np.min(img3d)\n        img3d = img3d / np.max(img3d)\n            \n    return np.expand_dims(img3d,0)\n\na = load_dicom_images_3d(\"00001\")\nprint(a.shape)\nprint(np.min(a), np.max(a), np.mean(a), np.median(a))\nimage = a[0]\nprint(\"Dimension of the CT scan is:\", image.shape)\nplt.imshow(np.squeeze(image[:, :, 30]), cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:02.431907Z","iopub.execute_input":"2021-09-23T03:45:02.432153Z","iopub.status.idle":"2021-09-23T03:45:03.219574Z","shell.execute_reply.started":"2021-09-23T03:45:02.432117Z","shell.execute_reply":"2021-09-23T03:45:03.218900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.utils import Sequence\nclass Dataset(Sequence):\n    def __init__(self,df,is_train=True,batch_size=1,shuffle=True):\n        self.idx = df[\"BraTS21ID\"].values\n        self.paths = df[\"BraTS21ID5\"].values\n        self.y =  df[\"MGMT_value\"].values\n        self.is_train = is_train\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n    def __len__(self):\n        return math.ceil(len(self.idx)/self.batch_size)\n   \n    def __getitem__(self,ids):\n        id_path= self.paths[ids]\n        batch_paths = self.paths[ids * self.batch_size:(ids + 1) * self.batch_size]\n        \n        if self.y is not None:\n            batch_y = self.y[ids * self.batch_size: (ids + 1) * self.batch_size]\n            \n        list_x =  load_dicom_images_3d(id_path)#str(scan_id).zfill(5)\n        #list_x =  [load_dicom_images_3d(x) for x in batch_paths]\n        batch_X = np.stack(list_x)\n        if self.is_train:\n            return batch_X,batch_y\n        else:\n            return batch_X\n    \n    def on_epoch_end(self):\n        if self.shuffle and self.is_train:\n            ids_y = list(zip(self.idx, self.y))\n            shuffle(ids_y)\n            self.idx, self.y = list(zip(*ids_y))","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:03.220703Z","iopub.execute_input":"2021-09-23T03:45:03.221429Z","iopub.status.idle":"2021-09-23T03:45:03.231281Z","shell.execute_reply.started":"2021-09-23T03:45:03.221393Z","shell.execute_reply":"2021-09-23T03:45:03.230333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = Dataset(test,is_train=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:03.232957Z","iopub.execute_input":"2021-09-23T03:45:03.233540Z","iopub.status.idle":"2021-09-23T03:45:03.247702Z","shell.execute_reply.started":"2021-09-23T03:45:03.233493Z","shell.execute_reply":"2021-09-23T03:45:03.246827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(1):\n    image = test_dataset[i]\n    print(\"Dimension of the CT scan is:\", image.shape)\n    plt.imshow(image[0,:,:, 32], cmap=\"gray\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:03.249029Z","iopub.execute_input":"2021-09-23T03:45:03.249317Z","iopub.status.idle":"2021-09-23T03:45:03.852762Z","shell.execute_reply.started":"2021-09-23T03:45:03.249278Z","shell.execute_reply":"2021-09-23T03:45:03.851574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(width=IMAGE_SIZE, height=IMAGE_SIZE, depth=64):\n    \"\"\"Build a 3D convolutional neural network model.\"\"\"\n\n    inputs = keras.Input((width, height, depth, 1))\n     \n    x = layers.Conv3D(filters=32, kernel_size=3, activation=\"relu\")(inputs)\n    x = layers.MaxPool3D(pool_size=2)(x)\n    x = layers.BatchNormalization()(x)\n    \n    x = layers.Conv3D(filters=32, kernel_size=3, activation=\"relu\")(inputs)\n    x = layers.MaxPool3D(pool_size=2)(x)\n    x = layers.BatchNormalization()(x)\n    \n    x = layers.Conv3D(filters=64, kernel_size=3, activation=\"relu\")(inputs)\n    x = layers.MaxPool3D(pool_size=2)(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Dropout(0.01)(x)\n    \n    x = layers.Conv3D(filters=128, kernel_size=3, activation=\"relu\")(x)\n    x = layers.MaxPool3D(pool_size=2)(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Dropout(0.02)(x)\n\n    x = layers.Conv3D(filters=256, kernel_size=3, activation=\"relu\")(x)\n    x = layers.MaxPool3D(pool_size=2)(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Dropout(0.03)(x)\n\n    x = layers.Conv3D(filters=512, kernel_size=3, activation=\"relu\")(x)\n    x = layers.MaxPool3D(pool_size=2)(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Dropout(0.04)(x)\n\n    x = layers.GlobalAveragePooling3D()(x)\n    x = layers.Dense(units=1024, activation=\"relu\")(x)\n    x = layers.Dropout(0.08)(x)\n\n    outputs = layers.Dense(units=1, activation=\"sigmoid\")(x)\n\n    # Define the model.\n    model = keras.Model(inputs, outputs, name=\"3dcnn\")\n\n    return model\n\n# Build model.\nmodel = get_model(width=IMAGE_SIZE, height=IMAGE_SIZE, depth=64)\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:03.854414Z","iopub.execute_input":"2021-09-23T03:45:03.854716Z","iopub.status.idle":"2021-09-23T03:45:04.180471Z","shell.execute_reply.started":"2021-09-23T03:45:03.854679Z","shell.execute_reply":"2021-09-23T03:45:04.179277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_weights('../input/brainclassification3d/Brain_3d_cls_FLAIR.h5')","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:04.182003Z","iopub.execute_input":"2021-09-23T03:45:04.182330Z","iopub.status.idle":"2021-09-23T03:45:05.019724Z","shell.execute_reply.started":"2021-09-23T03:45:04.182280Z","shell.execute_reply":"2021-09-23T03:45:05.019026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = model.predict(test_dataset)\npreds = preds.reshape(-1)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:45:05.020742Z","iopub.execute_input":"2021-09-23T03:45:05.021089Z","iopub.status.idle":"2021-09-23T03:51:40.116993Z","shell.execute_reply.started":"2021-09-23T03:45:05.021062Z","shell.execute_reply":"2021-09-23T03:51:40.116036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_bt3d = pd.DataFrame({'BraTS21ID':sample_submission['BraTS21ID'],'MGMT_value':preds})","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.118357Z","iopub.execute_input":"2021-09-23T03:51:40.118572Z","iopub.status.idle":"2021-09-23T03:51:40.124048Z","shell.execute_reply.started":"2021-09-23T03:51:40.118547Z","shell.execute_reply":"2021-09-23T03:51:40.123061Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_bt3d","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.125465Z","iopub.execute_input":"2021-09-23T03:51:40.125686Z","iopub.status.idle":"2021-09-23T03:51:40.144297Z","shell.execute_reply.started":"2021-09-23T03:51:40.125662Z","shell.execute_reply":"2021-09-23T03:51:40.143395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_bt3d.to_csv('submission_bt3d.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.145321Z","iopub.execute_input":"2021-09-23T03:51:40.145714Z","iopub.status.idle":"2021-09-23T03:51:40.152421Z","shell.execute_reply.started":"2021-09-23T03:51:40.145684Z","shell.execute_reply":"2021-09-23T03:51:40.151419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### miccai_fakeSubmission","metadata":{}},{"cell_type":"code","source":"submissionDF01 = pd.read_csv('../input/testsubmissions/submission (36).csv', dtype=str)\nsubmissionDF01 = submissionDF01.set_index('BraTS21ID')\nscoreDict01 = submissionDF01['MGMT_value'].to_dict()\nprint(scoreDict01)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.153996Z","iopub.execute_input":"2021-09-23T03:51:40.154380Z","iopub.status.idle":"2021-09-23T03:51:40.171537Z","shell.execute_reply.started":"2021-09-23T03:51:40.154328Z","shell.execute_reply":"2021-09-23T03:51:40.170655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"listOfStudyPaths = glob.glob('../input/rsna-miccai-brain-tumor-radiogenomic-classification/test/*')\nlistOfStudies = [eachPath.split('/')[-1] for eachPath in listOfStudyPaths]\n\npredList = []\nfor eachStudy in listOfStudies:\n    if eachStudy not in scoreDict01:\n        predList.append('0.500')\n    else:\n        score = float(scoreDict01[eachStudy])\n        predList.append(score)\n        \nsubmission_miccai = pd.DataFrame({'BraTS21ID':listOfStudies,'MGMT_value':predList})\nsubmission_miccai.to_csv('submission_miccai.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.176719Z","iopub.execute_input":"2021-09-23T03:51:40.177223Z","iopub.status.idle":"2021-09-23T03:51:40.186627Z","shell.execute_reply.started":"2021-09-23T03:51:40.177187Z","shell.execute_reply":"2021-09-23T03:51:40.186078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_miccai.sort_values(by='BraTS21ID', inplace=True)\nsubmission_miccai","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.187766Z","iopub.execute_input":"2021-09-23T03:51:40.188114Z","iopub.status.idle":"2021-09-23T03:51:40.202801Z","shell.execute_reply.started":"2021-09-23T03:51:40.188077Z","shell.execute_reply":"2021-09-23T03:51:40.202149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Efficientnet3D with one MRI type 0.674","metadata":{}},{"cell_type":"code","source":"import os\nimport sys \nimport json\nimport glob\nimport random\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\nimport torch.nn.functional as F\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.204158Z","iopub.execute_input":"2021-09-23T03:51:40.204524Z","iopub.status.idle":"2021-09-23T03:51:40.209865Z","shell.execute_reply.started":"2021-09-23T03:51:40.204488Z","shell.execute_reply":"2021-09-23T03:51:40.209274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if os.path.exists(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification\"):\n    data_directory = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\n    pytorch3dpath = \"../input/efficientnetpyttorch3d/EfficientNet-PyTorch-3D\"\nelse:\n    data_directory = '/media/roland/data/kaggle/rsna-miccai-brain-tumor-radiogenomic-classification'\n    pytorch3dpath = \"EfficientNet-PyTorch-3D\"\n    \nmri_types = ['FLAIR','T1w','T1wCE','T2w']\nSIZE = 256\nNUM_IMAGES = 64\n\nsys.path.append(pytorch3dpath)\nfrom efficientnet_pytorch_3d import EfficientNet3D","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.210857Z","iopub.execute_input":"2021-09-23T03:51:40.211180Z","iopub.status.idle":"2021-09-23T03:51:40.222041Z","shell.execute_reply.started":"2021-09-23T03:51:40.211155Z","shell.execute_reply":"2021-09-23T03:51:40.221371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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    data = data - np.min(data)\n    if np.max(data) != 0:\n        data = data / np.max(data)\n    \n    #data = (data * 255).astype(np.uint8)\n    data = cv2.resize(data, (img_size, img_size))\n    return data\n\ndef load_dicom_images_3d(scan_id, num_imgs=NUM_IMAGES, img_size=SIZE, mri_type=\"FLAIR\", split=\"train\"):\n\n    files = sorted(glob.glob(f\"{data_directory}/{split}/{scan_id}/{mri_type}/*.dcm\"))\n    \n    middle = len(files)//2\n    num_imgs2 = num_imgs//2\n    p1 = max(0, middle - num_imgs2)\n    p2 = min(len(files), middle + num_imgs2)\n    img3d = np.stack([load_dicom_image(f) for f in files[p1:p2]]).T \n    if img3d.shape[-1] < num_imgs:\n        n_zero = np.zeros((img_size, img_size, num_imgs - img3d.shape[-1]))\n        img3d = np.concatenate((img3d,  n_zero), axis = -1)\n            \n    return np.expand_dims(img3d,0)\n\nload_dicom_images_3d(\"00000\").shape","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.223124Z","iopub.execute_input":"2021-09-23T03:51:40.223479Z","iopub.status.idle":"2021-09-23T03:51:40.605998Z","shell.execute_reply.started":"2021-09-23T03:51:40.223452Z","shell.execute_reply":"2021-09-23T03:51:40.605313Z"},"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(42)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.607046Z","iopub.execute_input":"2021-09-23T03:51:40.607415Z","iopub.status.idle":"2021-09-23T03:51:40.612836Z","shell.execute_reply.started":"2021-09-23T03:51:40.607387Z","shell.execute_reply":"2021-09-23T03:51:40.612172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(f\"{data_directory}/train_labels.csv\")\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=42, \n    stratify=train_df[\"MGMT_value\"],\n)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.614150Z","iopub.execute_input":"2021-09-23T03:51:40.614350Z","iopub.status.idle":"2021-09-23T03:51:40.638216Z","shell.execute_reply.started":"2021-09-23T03:51:40.614327Z","shell.execute_reply":"2021-09-23T03:51:40.637360Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset(torch_data.Dataset):\n    def __init__(self, paths, targets=None, mri_type=None, label_smoothing=0.01, split=\"train\"):\n        self.paths = paths\n        self.targets = targets\n        self.mri_type = mri_type\n        self.label_smoothing = label_smoothing\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\": torch.tensor(data).float(), \"id\": scan_id}\n        else:\n            y = torch.tensor(abs(self.targets[index]-self.label_smoothing), dtype=torch.float)\n            return {\"X\": torch.tensor(data).float(), \"y\": y}","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.639578Z","iopub.execute_input":"2021-09-23T03:51:40.639968Z","iopub.status.idle":"2021-09-23T03:51:40.649848Z","shell.execute_reply.started":"2021-09-23T03:51:40.639924Z","shell.execute_reply":"2021-09-23T03:51:40.648883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.net = EfficientNet3D.from_name(\"efficientnet-b0\", override_params={'num_classes': 2}, in_channels=1)\n        n_features = self.net._fc.in_features\n        self.net._fc = nn.Linear(in_features=n_features, out_features=1, bias=True)\n    \n    def forward(self, x):\n        out = self.net(x)\n        return out","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.651053Z","iopub.execute_input":"2021-09-23T03:51:40.651359Z","iopub.status.idle":"2021-09-23T03:51:40.666434Z","shell.execute_reply.started":"2021-09-23T03:51:40.651331Z","shell.execute_reply":"2021-09-23T03:51:40.665500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modelfiles = None\n\nif not modelfiles:\n    modelfiles = ['FLAIR-e2-loss0.693-auc0.567.pth', 'T1w-e8-loss0.682-auc0.551.pth', 'T1wCE-e3-loss0.693-auc0.617.pth', 'T2w-e8-loss0.672-auc0.593.pth']\n    print(modelfiles)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.667990Z","iopub.execute_input":"2021-09-23T03:51:40.668322Z","iopub.status.idle":"2021-09-23T03:51:40.679593Z","shell.execute_reply.started":"2021-09-23T03:51:40.668280Z","shell.execute_reply":"2021-09-23T03:51:40.678969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.680421Z","iopub.execute_input":"2021-09-23T03:51:40.681022Z","iopub.status.idle":"2021-09-23T03:51:40.691078Z","shell.execute_reply.started":"2021-09-23T03:51:40.680988Z","shell.execute_reply":"2021-09-23T03:51:40.690422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(modelfile, df, mri_type, split):\n    print(\"Predict:\", modelfile, 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 = Model()\n    model.to(device)\n    \n    checkpoint = torch.load(f'../input/efficientnet3d-with-one-mri-type-0674/{modelfile}')\n    model.load_state_dict(checkpoint[\"model_state_dict\"])\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(batch[\"X\"].to(device))).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-09-23T03:51:40.691930Z","iopub.execute_input":"2021-09-23T03:51:40.692638Z","iopub.status.idle":"2021-09-23T03:51:40.704330Z","shell.execute_reply.started":"2021-09-23T03:51:40.692592Z","shell.execute_reply":"2021-09-23T03:51:40.703483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport pydicom\nimport cv2 as cv\n\nimport torch\nfrom torch import nn\nfrom torch.nn import functional as F\nfrom torch.utils.data import DataLoader, Dataset, Subset\n# from torchvision import models\nimport torchvision\nimport kornia as K  # batch image augmentations with torch.Tensor\nfrom kornia.augmentation import AugmentationSequential\nfrom kornia.augmentation.base import AugmentationBase3D  # Subclassing this is too complicated.\nfrom kornia.enhance import invert\n\nfrom tqdm.notebook import tqdm\n\nfrom pathlib import Path\nfrom typing import Union, Tuple, List, Optional, Type, Dict, Iterable\nimport time\n\nDEBUG = False\nREPRODUCTIVE = True\nINFERENCE_ONLY = True\nUSE_CROSS_VALIDATION = True\n\nrandom_state = 42\nmodel_name = \"Net-3D\"\ndata_dir = Path(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification\")\nmodels_dir = Path(\"../input/model-weights-for-rsna-miccai-brain-tumor-dataset\")\n# models_dir = Path(\".\")  # If train model with local machine\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\ntime_begin = time.time()\n\nif REPRODUCTIVE:\n    np.random.seed(random_state)\n    torch.random.manual_seed(random_state)\ndisplay(list(data_dir.iterdir()), torch.__version__, torchvision.__version__)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:40.705954Z","iopub.execute_input":"2021-09-23T03:51:40.707136Z","iopub.status.idle":"2021-09-23T03:51:41.229634Z","shell.execute_reply.started":"2021-09-23T03:51:40.707062Z","shell.execute_reply":"2021-09-23T03:51:41.228849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mri_series = {0: \"FLAIR\", 1: \"T1w\", 2: \"T1wCE\", 3: \"T2w\"}\nmri_series_map = {v: k for k, v in mri_series.items()}\nplanes = {0: \"Unknown\", 1: \"Coronal\", 2: \"Sagittal\", 3: \"Axial\"}\nplanes_map = {v: k for k, v in planes.items()}","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.231117Z","iopub.execute_input":"2021-09-23T03:51:41.231357Z","iopub.status.idle":"2021-09-23T03:51:41.236680Z","shell.execute_reply.started":"2021-09-23T03:51:41.231331Z","shell.execute_reply":"2021-09-23T03:51:41.235710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_train = pd.read_csv(data_dir / \"train_labels.csv\", dtype={\"BraTS21ID\": str})\nlabels_train","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.238188Z","iopub.execute_input":"2021-09-23T03:51:41.238502Z","iopub.status.idle":"2021-09-23T03:51:41.262839Z","shell.execute_reply.started":"2021-09-23T03:51:41.238470Z","shell.execute_reply":"2021-09-23T03:51:41.261981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def look_one_dcm(instance_id: str, img_dir: Path, mri_series=\"FLAIR\", verbose=False):\n    dcm_paths = list(img_dir.glob(\"./{}/{}/*.dcm\".format(instance_id.zfill(5), mri_series)))\n    print(\"Containing {} dicom files(including blank).\".format(len(dcm_paths)))\n    if dcm_paths:\n        dcm_mid = dcm_paths[(len(dcm_paths) - 1) // 2]\n        dcm_ds = pydicom.read_file(str(dcm_mid))\n        if verbose:\n            print(dir(dcm_ds))\n            print(dcm_ds)\n            print(type(dcm_ds[(\"0010\", \"0010\")].value))\n            print(dcm_ds[(\"0020\", \"0032\")].name, eval(str(dcm_ds[(\"0020\", \"0032\")].value)))\n            print(dir(dcm_ds[(\"0020\", \"0032\")]))\n            print(dcm_ds.pixel_array.dtype)\n        plt.imshow(dcm_ds.pixel_array, cmap=plt.cm.gray)\n        plt.show()\n\n\nlook_one_dcm(\"00000\", data_dir / \"train\", verbose=True)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.264308Z","iopub.execute_input":"2021-09-23T03:51:41.264755Z","iopub.status.idle":"2021-09-23T03:51:41.497043Z","shell.execute_reply.started":"2021-09-23T03:51:41.264721Z","shell.execute_reply":"2021-09-23T03:51:41.496191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_image_plane(loc):\n    row_x, row_y, row_z, col_x, col_y, col_z = [round(v) for v in loc]\n    if (row_x, row_y, col_x, col_y) == (1, 0, 0, 0): return planes[1]\n    if (row_x, row_y, col_x, col_y) == (0, 1, 0, 0): return planes[2]\n    if (row_x, row_y, col_x, col_y) == (1, 0, 0, 1): return planes[3]\n    return planes[0]\n\n\nclass DICOMMetaLoader(Dataset):\n    \n    def __init__(self, img_dir: Path, glob=None):\n        super(DICOMMetaLoader, self).__init__()\n        if glob is None:\n            glob = \"./*/*/*.dcm\"\n        self.dcm_paths = list(img_dir.glob(glob))\n    \n    def __len__(self): return len(self.dcm_paths)\n    \n    def __getitem__(self, idx) -> dict:\n        dcm_path = str(self.dcm_paths[idx])\n        dcm_obj = pydicom.read_file(dcm_path)\n        photometric = str(dcm_obj[0x28, 0x04])\n        array = dcm_obj.pixel_array\n        if photometric == \"MONOCHROME1\":\n            info_func = np.iinfo if np.issubdtype(array.dtype, np.integer) else np.finfo\n            array = info_func(array.dtype).max - array\n        image_mean, image_std = np.mean(array), np.std(array)\n        \n        impo_x, impo_y, impo_z = [float(v) for v in dcm_obj[0x20, 0x32]]\n        plane = get_image_plane(dcm_obj[0x20, 0x37])\n        \n        patient_id = str(dcm_obj[0x0010, 0x0020].value).strip().zfill(5)\n        series_desc = str(dcm_obj[0x0008, 0x103e].value).strip()\n        row = dict(dcm_path=dcm_path, BraTS21ID=patient_id, series_description=series_desc,\n                   image_mean=image_mean, image_std=image_std,\n                   plane=plane,\n                   image_position_x=impo_x, image_position_y=impo_y, image_position_z=impo_z)\n        return row\n\n\ndef get_meta_from_glob(img_dir: Path, glob=None) -> pd.DataFrame:\n    dcm_ds = DICOMMetaLoader(img_dir, glob)\n    dcm_dl = DataLoader(dcm_ds, batch_size=256, num_workers=6)\n    df = pd.DataFrame()\n    for item in tqdm(dcm_dl):\n        chunks = pd.DataFrame.from_dict({k:np.asarray(v) for k, v in item.items()})\n        df = pd.concat([df, chunks], ignore_index=True)\n    return df\n\n\n# df_train = get_meta_from_glob(data_dir / \"train\")","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.498292Z","iopub.execute_input":"2021-09-23T03:51:41.498534Z","iopub.status.idle":"2021-09-23T03:51:41.512562Z","shell.execute_reply.started":"2021-09-23T03:51:41.498506Z","shell.execute_reply":"2021-09-23T03:51:41.511687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # To categorical data by mapping, \n\n# df_train.loc[:, \"plane\"] = df_train.loc[:, \"plane\"].map(planes_map)\n# df_train.loc[:, \"series_description\"] = df_train.loc[:, \"series_description\"].map(mri_series_map)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.514145Z","iopub.execute_input":"2021-09-23T03:51:41.514429Z","iopub.status.idle":"2021-09-23T03:51:41.528689Z","shell.execute_reply.started":"2021-09-23T03:51:41.514401Z","shell.execute_reply":"2021-09-23T03:51:41.527661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def keep_non_blank(df: pd.DataFrame):\n    \"\"\"\n    Keep data containing non blank image.\n    :params:\n        df: pd.DataFrame, requires \"image_std\" and \"image_mean\" in df.columns.\n    :returns:\n        pd.DataFrame: filtered DataFrame\n    \"\"\"\n    df = df.loc[(df[\"image_std\"] > 0) & (df[\"image_mean\"] > 0)]\n    return df\n\n\n# display(len(df_train))\n# df_train = keep_non_blank(df_train)\n# display(len(df_train))","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.530364Z","iopub.execute_input":"2021-09-23T03:51:41.530603Z","iopub.status.idle":"2021-09-23T03:51:41.540042Z","shell.execute_reply.started":"2021-09-23T03:51:41.530574Z","shell.execute_reply":"2021-09-23T03:51:41.539225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def drop_by_id(df: pd.DataFrame, ids: List[Union[int, str]]):\n    ids = [str(s).zfill(5) for s in ids]\n    df = df.loc[~(df[\"BraTS21ID\"].isin(ids))].reset_index(drop=True)\n    return df\n\n\n# drop_ids = \"00109, 00123, 00709\".split(\", \")\n# df_train = drop_by_id(df_train, drop_ids)\n# labels_train = drop_by_id(labels_train, drop_ids)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.541284Z","iopub.execute_input":"2021-09-23T03:51:41.541519Z","iopub.status.idle":"2021-09-23T03:51:41.552264Z","shell.execute_reply.started":"2021-09-23T03:51:41.541491Z","shell.execute_reply":"2021-09-23T03:51:41.551424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def count_values(df: pd.DataFrame):\n    groupby = df.groupby([\"BraTS21ID\", \"series_description\"])\n    count = groupby.count()\n    display(count[\"dcm_path\"].describe())\n    display(count.loc[count[\"dcm_path\"] == count[\"dcm_path\"].min(), \"dcm_path\"])\n    display(count.loc[count[\"dcm_path\"] == count[\"dcm_path\"].max(), \"dcm_path\"])\n\n\n# display(df_train.describe())\n# count_values(df_train)\n# look_one_dcm(\"00571\", data_dir / \"train\", mri_series[0])\n# look_one_dcm(\"00818\", data_dir / \"train\", mri_series[0])\n# look_one_dcm(\"00012\", data_dir / \"train\", mri_series[3])","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.553745Z","iopub.execute_input":"2021-09-23T03:51:41.554134Z","iopub.status.idle":"2021-09-23T03:51:41.567503Z","shell.execute_reply.started":"2021-09-23T03:51:41.554075Z","shell.execute_reply":"2021-09-23T03:51:41.566587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class MRIVoxelDataset(Dataset):\n    \n    def __init__(self, meta_df: pd.DataFrame, label_df: Optional[pd.DataFrame] = None,\n                 voxel_size: Union[int, Tuple[int, int], Tuple[int, int, int]] = (64, 256, 256),\n                 including_series: np.ndarray = np.array(list(mri_series.keys()), dtype=np.int64)):\n        \"\"\"\n        :params:\n            :meta_df: required columns: [dcm_path, BraTS21ID, series_description, plane,\n                                         image_position_x, image_position_y, image_position_z]\n            :label_df(Optional): required columns: [BraTS21ID, MGMT_value]\n            :voxel_size: if int, the D, H, W will be set to the same;\n                         if (int, int), D by voxel_size[0], H, W by voxel_size[1];\n                         if (int, int, int), D, H, W will be set respectively.\n        \"\"\"\n        super(MRIVoxelDataset, self).__init__()\n        self.meta_df,self.label_df,self.voxel_size = meta_df,label_df,voxel_size\n        self.including_series = including_series\n        if isinstance(self.voxel_size, int):\n            self.voxel_size = tuple(self.voxel_size for _ in range(3))\n        elif isinstance(self.voxel_size, tuple):\n            if len(self.voxel_size) == 2:\n                self.voxel_size = (self.voxel_size[0], self.voxel_size[1], self.voxel_size[1])\n        self.meta_df = self.meta_df.loc[self.meta_df[\"series_description\"].isin(self.including_series)].copy()\n        if self.label_df is None:\n            self.label_df = pd.concat([pd.DataFrame.from_dict(\n                dict(BraTS21ID=self.meta_df[\"BraTS21ID\"].unique())\n            )], axis=1)\n            self.label_df.loc[:, \"BraTS21ID\"] = self.label_df[\"BraTS21ID\"].map(lambda i: str(i).zfill(5))\n            labels = np.full_like(self.label_df[\"BraTS21ID\"].values, np.nan, dtype=np.float64)\n            self.label_df.loc[:, \"MGMT_value\"] = labels\n\n        new_label_df = pd.DataFrame()\n        for v in self.meta_df[\"series_description\"].unique():\n            series_desc = pd.DataFrame({\n                    \"series_description\": np.full((len(self.label_df)), v, dtype=np.int64)\n                 })\n            df = self.label_df.reset_index(drop=True)\n            df = pd.concat([df, series_desc], axis=1)\n            new_label_df = pd.concat([new_label_df, df], axis=0)\n        self.label_df = new_label_df.reset_index(drop=True)\n\n        retrievables = list()\n        for i in range(len(self.label_df)):\n            row = self.label_df.iloc[i]\n            flag = is_retrievable(self.meta_df, row.BraTS21ID, row.series_description)\n            if not flag:\n                print(row.BraTS21ID, row.series_description)\n            retrievables.append(flag)\n        retrievables = np.asarray(retrievables)\n        self.label_df = self.label_df.iloc[retrievables]\n        print(f\"Got {len(self)} samples in dataset.\")\n\n    def __len__(self): return len(self.label_df)\n    \n    def __getitem__(self, idx):\n        row = self.label_df.iloc[idx]\n        voxel, plane = get_voxel_by_id_series(self.meta_df, row[\"BraTS21ID\"], row[\"series_description\"], self.voxel_size[1:])\n        voxel = torch.tensor(voxel, dtype=torch.float32).unsqueeze(0).unsqueeze(0)  # [N, C, D, H, W]\n        voxel = F.interpolate(voxel, self.voxel_size, mode=\"trilinear\", align_corners=False)\n        voxel = voxel.squeeze(0)\n        label = torch.tensor([row[\"MGMT_value\"]], dtype=torch.float32)\n        plane = torch.tensor(plane, dtype=torch.int64)\n        series_desc = torch.tensor(row[\"series_description\"], dtype=torch.int64)\n        return voxel, label, (series_desc, plane)\n\n\n# if DEBUG:\n#     ds_ = MRIVoxelDataset(df_train, labels_train, (64, 128), np.array([0], dtype=np.int64))\n#     dl_ = DataLoader(ds_, batch_size=4, num_workers=4)\n#     for voxel, label, (series_desc, plane) in dl_:\n#         print(voxel.shape, label.shape, plane.shape, series_desc.shape)\n#         print(voxel.dtype, label.dtype, plane.dtype, series_desc.dtype)\n#         break","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.569268Z","iopub.execute_input":"2021-09-23T03:51:41.570044Z","iopub.status.idle":"2021-09-23T03:51:41.590589Z","shell.execute_reply.started":"2021-09-23T03:51:41.569994Z","shell.execute_reply":"2021-09-23T03:51:41.589783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NormLayerClass = Type\nActivationLayerClass = Type\n\n\nclass SqueezeExcitation(nn.Module):\n    \n    def __init__(self, in_channels):\n        super(SqueezeExcitation, self).__init__()\n        self.in_channels = in_channels\n        self.squeeze_channels = self.in_channels // 4\n        \n        self.seq = nn.Sequential(\n            nn.AdaptiveAvgPool3d(1),\n            nn.Conv3d(self.in_channels, self.squeeze_channels, 1),\n            nn.ReLU(inplace=True),\n            nn.Conv3d(self.squeeze_channels, self.in_channels, 1),\n            nn.Hardsigmoid(inplace=True),\n        )\n    \n    def forward(self, x):\n        scale = self.seq(x)\n        out = scale * x\n        return out\n\n\nclass ConvBNActivation(nn.Module):\n    \n    def __init__(self, conv_config: dict,\n                 norm_layer_cls: NormLayerClass = nn.BatchNorm3d,\n                 activation_layer_cls: ActivationLayerClass = nn.ReLU,\n                 use_se: bool = False,\n        ) -> None:\n        super(ConvBNActivation, self).__init__()\n        layers = list()\n        layers.append(nn.Conv3d(**conv_config))\n        layers.append(norm_layer_cls(conv_config[\"out_channels\"]))\n        layers.append(activation_layer_cls(inplace=True))\n        if use_se:\n            layers.append(SqueezeExcitation(conv_config[\"out_channels\"]))\n        self.seq = nn.Sequential(*layers)\n    \n    def forward(self, x):\n        return self.seq(x)\n    \n    @staticmethod\n    def config(in_channels: int,\n               out_channels: int,\n               kernel_size: Union[int, Tuple[int, int, int]],\n               stride: Union[int, Tuple[int, int, int]] = 1,\n               padding: Union[int, Tuple[int, int, int]] = 0,\n               dilation: Union[int, Tuple[int, int, int]] = 1,\n               groups: int = 1,\n               bias: bool = True,\n               padding_mode: str = 'zeros',\n        ) -> dict:\n        return locals()\n\n\nclass BottleNeck(nn.Module):\n    \n    def __init__(self, residual_config: dict):\n        super(BottleNeck, self).__init__()\n        self.residual_config = residual_config\n        layers = list()\n        layers.append(ConvBNActivation(ConvBNActivation.config(\n            self.residual_config[\"in_channels\"],\n            self.residual_config[\"expand_channels\"],\n            1,\n            1,\n            0,\n        ), self.residual_config[\"norm_layer_cls\"], self.residual_config[\"activation_layer_cls\"]))\n        layers.append(ConvBNActivation(ConvBNActivation.config(\n            self.residual_config[\"expand_channels\"],\n            self.residual_config[\"expand_channels\"],\n            self.residual_config[\"kernel_size\"],\n            self.residual_config[\"stride\"],\n            self.residual_config[\"padding\"],\n            groups=self.residual_config[\"expand_channels\"],\n        ), self.residual_config[\"norm_layer_cls\"],\n           self.residual_config[\"activation_layer_cls\"],\n           self.residual_config[\"use_se\"]))\n        layers.append(ConvBNActivation(ConvBNActivation.config(\n            self.residual_config[\"expand_channels\"],\n            self.residual_config[\"out_channels\"],\n            1,\n            1,\n            0,\n        ), self.residual_config[\"norm_layer_cls\"], nn.Identity))\n        self.seq = nn.Sequential(*layers)\n        # The shortcut: Same as nn.Linear if channels at last dim.\n        self.shortcut = nn.Conv3d(self.residual_config[\"in_channels\"], self.residual_config[\"out_channels\"], 1)\n    \n    def forward(self, x):\n        post_seq = self.seq(x)\n        x = self.shortcut(x)\n        x = F.interpolate(x, post_seq.shape[-3:], mode=\"trilinear\", align_corners=False)\n        return x + post_seq\n    \n    @staticmethod\n    def config(in_channels: int,\n               out_channels: int,\n               expand_channels: int,\n               kernel_size: Union[int, Tuple[int, int, int]],\n               stride: Union[int, Tuple[int, int, int]] = 1,\n               padding: Union[int, Tuple[int, int, int]] = 0,\n               norm_layer_cls: NormLayerClass = nn.BatchNorm3d,\n               activation_layer_cls: ActivationLayerClass = nn.Hardswish,\n               use_se: bool = False,\n    ) -> dict:\n        return locals()\n\n\nclass NetFeatures(nn.Module):\n    \n    def __init__(self, in_channels, out_channels, residual_config_list: List[dict]):\n        super(NetFeatures, self).__init__()\n        self.in_channels,self.out_channels = in_channels,out_channels\n        self.residual_config_list = residual_config_list\n\n        first_conv_out_channels = self.residual_config_list[0][\"in_channels\"]\n        self.first_conv = ConvBNActivation(ConvBNActivation.config(\n            self.in_channels, first_conv_out_channels, 3, 2, 1), activation_layer_cls=nn.ReLU)\n        residual_layers = list()\n        for conf in self.residual_config_list:\n            residual_layers.append(BottleNeck(conf))\n        self.residual_block = nn.Sequential(*residual_layers)\n        last_conv_in_channels = self.residual_config_list[-1][\"out_channels\"]\n        self.last_conv = ConvBNActivation(ConvBNActivation.config(last_conv_in_channels, self.out_channels, 1),\n                                          nn.BatchNorm3d,\n                                          nn.Hardswish,\n                                          use_se=True)\n    \n    def forward(self, x):\n        x = self.first_conv(x)\n        x = self.residual_block(x)\n        x = self.last_conv(x)\n        return x\n\n\nclass ConcatEmbeddingLinear(nn.Module):\n    \n    def __init__(self, in_features: int, out_features: int, n_embeddings: int, embed_dim: Optional[int] = None):\n        super(ConcatEmbeddingLinear, self).__init__()\n        self.in_features,self.out_features = in_features,out_features\n        self.n_embeddings,self.embed_dim = n_embeddings,embed_dim\n        if self.embed_dim is None: self.embed_dim = self.in_features\n        \n        self.emb = nn.Embedding(self.n_embeddings, self.embed_dim)\n        self.fc = nn.Linear(self.in_features + self.embed_dim, self.out_features)\n    \n    def forward(self, x, idx_emb):\n        emb_out = self.emb(idx_emb)\n        concatenated = torch.cat([emb_out, x], dim=-1)\n        out = self.fc(concatenated)\n        return out\n\n\nclass Net(nn.Module):\n    \n    def __init__(self, in_channels, feature_out_channels, hidden_features, n_classes, n_series, n_planes,\n                 residual_config_list: List[dict]) -> None:\n        super(Net, self).__init__()\n        self.in_channels,self.feature_out_channels,self.n_classes = in_channels,feature_out_channels,n_classes\n        self.hidden_features = hidden_features\n        self.n_planes,self.n_series = n_planes,n_series\n        self.residual_config_list = residual_config_list\n        \n        self.features = NetFeatures(self.in_channels, self.feature_out_channels, self.residual_config_list)\n        self.pool_flat_linear = nn.Sequential(nn.AdaptiveAvgPool3d(1),\n            nn.Flatten(),\n            nn.Linear(self.features.out_channels, self.hidden_features),\n        )\n        self.emb_series = ConcatEmbeddingLinear(self.hidden_features, self.hidden_features, self.n_series)\n        self.emb_planes = ConcatEmbeddingLinear(self.hidden_features, self.hidden_features, self.n_planes)\n        self.classifier = nn.Sequential(\n            nn.Dropout(0.2),\n            nn.Linear(self.hidden_features, self.n_classes)\n        )\n\n    def forward(self, x, idx_series, idx_planes):\n        x = self.features(x)\n        x = self.pool_flat_linear(x)\n        x = self.emb_series(x, idx_series)\n        x = self.emb_planes(x, idx_planes)\n        out = self.classifier(x)\n        return out\n\n\ndef get_residual_config_backup():\n    # Like MobileNetV3 small, although it may be too deep.\n    # in_channels, out_channels, expand_channels, kernel_size, stride, padding, norm, activation, use_se\n    conf = list()\n    conf.append(BottleNeck.config(16, 16, 16, 3, 2, 1, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(16, 24, 72, 3, 2, 1, nn.BatchNorm3d, nn.ReLU, False))\n    conf.append(BottleNeck.config(24, 24, 88, 3, 1, 1, nn.BatchNorm3d, nn.ReLU, False))\n    conf.append(BottleNeck.config(24, 40, 96, 5, 2, 2, nn.BatchNorm3d, nn.ReLU, True))\n    conf.append(BottleNeck.config(40, 40, 240, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(40, 40, 240, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(40, 48, 120, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(48, 48, 144, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(48, 96, 288, 5, 2, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(96, 96, 576, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(96, 96, 576, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    return conf\n\n\ndef get_residual_config():\n    # in_channels, out_channels, expand_channels, kernel_size, stride, padding, norm, activation, use_se\n    conf = list()\n    conf.append(BottleNeck.config(16, 16, 16, 3, 2, 1, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(16, 24, 72, 3, 2, 1, nn.BatchNorm3d, nn.ReLU, False))\n    conf.append(BottleNeck.config(24, 24, 88, 3, 1, 1, nn.BatchNorm3d, nn.ReLU, False))\n    conf.append(BottleNeck.config(24, 40, 96, 5, 2, 2, nn.BatchNorm3d, nn.ReLU, True))\n    conf.append(BottleNeck.config(40, 40, 240, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(40, 80, 288, 5, 2, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    conf.append(BottleNeck.config(80, 96, 576, 5, 1, 2, nn.BatchNorm3d, nn.Hardswish, True))\n    return conf\n\n\nif DEBUG:\n    t_ = torch.ones(4, 1, 64, 256, 256, dtype=torch.float32)\n    l_ = torch.ones(4, 1, dtype=torch.float32)\n    s_ = torch.ones(4, dtype=torch.int64)\n    p_ = torch.ones(4, dtype=torch.int64)\n    config_ = get_residual_config()\n    net_ = Net(1, 512, 512, 1, 4, 4, config_).to(dtype=torch.float32)\n    print(net_)\n    with torch.no_grad():\n        o_ = net_(t_, s_, p_)\n        loss_ = F.binary_cross_entropy_with_logits(o_, l_)\n        print(loss_.item())","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.591895Z","iopub.execute_input":"2021-09-23T03:51:41.592487Z","iopub.status.idle":"2021-09-23T03:51:41.642686Z","shell.execute_reply.started":"2021-09-23T03:51:41.592440Z","shell.execute_reply":"2021-09-23T03:51:41.641746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(path, *net_args, **net_kwargs):\n    net = Net(*net_args, **net_kwargs)\n    state_dict = torch.load(path)\n    net.load_state_dict(state_dict)\n    return net","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.644054Z","iopub.execute_input":"2021-09-23T03:51:41.644418Z","iopub.status.idle":"2021-09-23T03:51:41.658807Z","shell.execute_reply.started":"2021-09-23T03:51:41.644368Z","shell.execute_reply":"2021-09-23T03:51:41.658112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RandomInvert3D(AugmentationBase3D):\n    \n    def __init__(\n        self,\n        max_val: Union[float, torch.Tensor] = torch.tensor(1.0),\n        return_transform: bool = False,\n        same_on_batch: bool = False,\n        p: float = 0.5,\n    ) -> None:\n        super(RandomInvert3D, self).__init__(\n            p=p, return_transform=return_transform, same_on_batch=same_on_batch, p_batch=1.0\n        )\n        self.max_val = max_val\n\n    def __repr__(self) -> str:\n        return self.__class__.__name__ + f\"({super().__repr__()})\"\n    \n    def generate_parameters(self, batch_shape: torch.Size):\n        return dict(max_val=torch.as_tensor(self.max_val), batch_shape=torch.as_tensor(batch_shape))\n    \n    def compute_transformation(self, input, params: Dict[str, torch.Tensor]):\n        return self.identity_matrix(input)\n\n    def apply_transform(\n        self, input: torch.Tensor,\n        params: Dict[str, torch.Tensor],\n        transform: Optional[torch.Tensor] = None\n    ) -> torch.Tensor:\n        max_val = params[\"max_val\"]\n        return invert(input, max_val)\n\n    \nNumeric = Union[int, float]\n\n\nclass RandomShift3D(nn.Module):\n    \n    def __init__(self,\n                 shift_limit: Union[Numeric, List[Numeric], Tuple[Numeric, Numeric]] = 0.125,\n                 p: float = 0.5):\n        super(RandomShift3D, self).__init__()\n        self.shift_limit,self.p = shift_limit,p\n        if isinstance(self.shift_limit, (float, int)):\n            self.shift_limit = np.array(((-abs(self.shift_limit), abs(self.shift_limit)),\n                                         (-abs(self.shift_limit), abs(self.shift_limit)),\n                                         (-abs(self.shift_limit), abs(self.shift_limit)),), dtype=np.float64)\n        elif isinstance(self.shift_limit, (tuple, list)):\n            self.shift_limit = np.array(self.shift_limit, dtype=np.float64)\n        else:\n            raise TypeError(\"shift_limit expects \")\n        self.shift_limit = np.clip(self.shift_limit, -1., 1.)\n        if self.shift_limit.shape[0] == 1:\n            self.shift_limit = np.concatenate([self.shift_limit, self.shift_limit, self.shift_limit])\n        assert self.shift_limit.shape == (3, 2), f\"\"\n    \n    def forward(self, tensor):\n        assert len(tensor.shape) == 5, f\"Requires 5 dims torch.Tensor[N, C, D, H, W], got {tensor.shape}\"\n        n, c, d, h, w = tensor.shape\n        apply_proba = np.random.uniform(size=(n,))\n        shift_size = np.random.uniform(low=self.shift_limit[:, 0], high=self.shift_limit[:, 1], size=(n, 3))\n        shift_d, shift_h, shift_w = (np.array(tensor.shape[2:])[np.newaxis, :] * shift_size).astype(np.int64).T\n        out = torch.zeros_like(tensor)\n        for i in range(n):\n            if apply_proba[i] <= self.p:\n                out[i, :,\n                    max(0, 0+shift_d[i]):min(d, d+shift_d[i]),\n                    max(0, 0+shift_h[i]):min(h, h+shift_h[i]),\n                    max(0, 0+shift_w[i]):min(w, w+shift_w[i]),\n                ] = tensor[i, :,\n                    max(0, 0-shift_d[i]):min(d, d-shift_d[i]),\n                    max(0, 0-shift_h[i]):min(h, h-shift_h[i]),\n                    max(0, 0-shift_w[i]):min(w, w-shift_w[i]),\n                ]\n            else:\n                out[i] = tensor[i]  # Unchanged.\n        return out\n\n\ndef get_augmentation(split=\"train\") -> nn.Sequential:\n    \"\"\"\n    Get Sequence of augmentations.\n    :return: nn.Sequential: requires input: torch.FloatTensor[N, C, D, H, W] in range[0., 1.]\n    \"\"\"\n    if split in (\"test\", \"val\"):\n        aug_list = nn.Sequential()\n    elif split == \"train\":\n        aug_list = nn.Sequential(\n            K.augmentation.RandomAffine3D(degrees=(5., 5., 90.), translate=(.05, .05, .05), scale=(.98, 1.02), p=.3),\n            K.augmentation.RandomHorizontalFlip3D(p=.3),\n#             K.augmentation.RandomVerticalFlip3D(p=.1),\n#             K.augmentation.RandomRotation3D((0., 0., 90.), p=1.0)\n            RandomShift3D(shift_limit=0.2, p=.3),\n            RandomInvert3D(p=.1),\n        )\n    else:\n        raise ValueError(f\"Argument `split` must in {{'train', 'val', 'test'}}, got {split}\")\n    aug_list.requires_grad_(False)\n    return aug_list\n\n\ndef plot_grid(t: torch.tensor) -> None:\n    \"\"\"\n    Plot image by middle index\n    :argument: t: torch.Tensor[N, C, D, H, W]\n    \"\"\"\n    from itertools import product\n    a = int(np.ceil(np.sqrt(len(t))))\n    fig, axes = plt.subplots(a, a, figsize=(14, 14))\n    for nth, (i, j) in zip(range(len(t)), product(range(a), range(a))):\n        nth_img = t[nth].squeeze(0).numpy()\n        nth_img_mid = nth_img[len(nth_img) // 2]\n        mean, std = np.mean(nth_img), np.std(nth_img)\n        axes[i, j].imshow(nth_img_mid, cmap=plt.cm.gray)\n        axes[i, j].set_title(f\"mean: {mean:.4f}, std: {std:.4f}\")\n        axes[i, j].set_axis_off()\n    plt.show()\n\n\n# # Check the effect of augmentation.\n# ds_ = MRIVoxelDataset(df_train, labels_train, (64, 128))\n# dl_ = DataLoader(ds_, batch_size=16, shuffle=True, num_workers=6)\n# aug_ = get_augmentation(split=\"train\")\n# for voxel, label, (_, _) in dl_:\n#     voxel = aug_(voxel)\n#     plot_grid(voxel)\n#     break","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.660082Z","iopub.execute_input":"2021-09-23T03:51:41.660672Z","iopub.status.idle":"2021-09-23T03:51:41.688508Z","shell.execute_reply.started":"2021-09-23T03:51:41.660624Z","shell.execute_reply":"2021-09-23T03:51:41.687903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters to construct Net\nin_channels = 1\nfeature_out_channels = 576\nhidden_features = 512\nn_classes = 1\nn_series = len(mri_series)\nn_planes = len(planes)\nresidual_config = get_residual_config()\n\n# Training Parameters\nbatch_size = 16\nepochs = 18\nlr = 3e-4\nnum_workers = 6\nweight_decay = 1e-5","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.689695Z","iopub.execute_input":"2021-09-23T03:51:41.690070Z","iopub.status.idle":"2021-09-23T03:51:41.704817Z","shell.execute_reply.started":"2021-09-23T03:51:41.690029Z","shell.execute_reply":"2021-09-23T03:51:41.704119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"voxel_size = (64, 64, 64)\nincluding_series = np.array([\n    mri_series_map[\"FLAIR\"],\n    mri_series_map[\"T1w\"],\n    mri_series_map[\"T1wCE\"],\n    mri_series_map[\"T2w\"],\n], dtype=np.int64)\nNumpyNDArray = Iterable\n\ndef get_dataset_in_pipeline(img_dir: Path, including_series: NumpyNDArray[np.int64],\n                            voxel_size: Union[int, Tuple[int, int], Tuple[int, int, int]] = (64, 256, 256),\n                            glob: str = None,\n                            df_labels: pd.DataFrame = None, drop_ids: List[str] = None):\n    df_meta = get_meta_from_glob(img_dir, glob)\n    df_meta.loc[:, \"plane\"] = df_meta.loc[:, \"plane\"].map(planes_map)\n    df_meta.loc[:, \"series_description\"] = df_meta.loc[:, \"series_description\"].map(mri_series_map)\n    df_meta = keep_non_blank(df_meta)\n    if df_labels is not None:\n        df_labels = drop_by_id(df_labels, drop_ids)\n        df_meta = drop_by_id(df_meta, drop_ids)\n    ds = MRIVoxelDataset(df_meta, df_labels, voxel_size, including_series)\n    return ds","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.705935Z","iopub.execute_input":"2021-09-23T03:51:41.706329Z","iopub.status.idle":"2021-09-23T03:51:41.717000Z","shell.execute_reply.started":"2021-09-23T03:51:41.706285Z","shell.execute_reply":"2021-09-23T03:51:41.716384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def is_retrievable(df: pd.DataFrame,\n                   patient_id: str,\n                   series_desc_idx: int):\n    retrieved_idx = (df[\"BraTS21ID\"].eq(patient_id)) & (df[\"series_description\"].eq(series_desc_idx))\n    return True if retrieved_idx.sum() > 0 else False\n\n\ndef get_voxel_by_id_series(df: pd.DataFrame,\n                           patient_id: str,\n                           series_desc_idx: int = 0,\n                           size: Union[int, Tuple[int, int]] = 256) -> Tuple[np.ndarray, int]:\n    \"\"\"\n    :params:\n        :df: required columns: [dcm_path, BraTS21ID, series_description, plane,\n                                image_position_x, image_position_y, image_position_z]\n    \"\"\"\n    size = (int(size), int(size)) if isinstance(size, (int, float)) else size\n    retrieved_idx = (df[\"BraTS21ID\"].eq(patient_id)) & (df[\"series_description\"].eq(series_desc_idx))\n    assert retrieved_idx.sum() > 0, \"Nothing retrived.\"\n    retrieved_df = df.loc[retrieved_idx].copy()\n    plane = retrieved_df[\"plane\"].unique()\n    assert len(plane) == 1, \"Different plane in a folder.\"\n    img_pos_cols = [c for c in retrieved_df.columns if c.startswith(\"image_position_\")]\n    img_pos_stds = np.array([retrieved_df[c].std() for c in img_pos_cols])\n    img_pos_argsort = np.argsort(img_pos_stds)[::-1]\n    sorted_df = retrieved_df.sort_values([img_pos_cols[i] for i in img_pos_argsort], ascending=True, ignore_index=True)\n    voxel_stack = list()\n    for row in sorted_df.itertuples():\n        dcm_obj = pydicom.read_file(row.dcm_path)\n        array = dcm_obj.pixel_array\n        array = cv.resize(array, size)\n        dinfo = np.iinfo(array.dtype) if np.issubdtype(array.dtype, np.integer) else np.finfo(array.dtype)\n        array = (array / dinfo.max).astype(np.float32)  # like (a / 255) if a.dtype is uint8\n        if dcm_obj[0x0028, 0x0004] == \"MONOCHROME1\":\n            array = dinfo.max - array\n        voxel_stack.append(array)\n    voxel = np.stack(voxel_stack)\n    voxel = (voxel - np.min(voxel)) / max(np.max(voxel), 1e-8)  # min-max normalization\n    return voxel, plane[0]\n\n\ndef plot_voxel(voxel, max_n_plots=10, cols=10):\n    actual_n_plots = min(max_n_plots, len(voxel))\n    rows = int(np.ceil(actual_n_plots / cols))\n    fig, axes = plt.subplots(rows, cols, figsize=(4 * cols, 4 * rows), tight_layout=True)\n    for i in range(actual_n_plots):\n        axes[i // cols, i % cols].imshow(voxel[i, :, :], cmap=plt.cm.gray)\n        axes[i // cols, i % cols].set_axis_off()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.718205Z","iopub.execute_input":"2021-09-23T03:51:41.718567Z","iopub.status.idle":"2021-09-23T03:51:41.735453Z","shell.execute_reply.started":"2021-09-23T03:51:41.718536Z","shell.execute_reply":"2021-09-23T03:51:41.734492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import dependencies \nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt \n%matplotlib inline\n\nimport os, sys, glob, gc \nimport math, re, random, time\nfrom tqdm import tqdm \nimport cv2, pydicom\n\nfrom sklearn.model_selection import StratifiedKFold \n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.737009Z","iopub.execute_input":"2021-09-23T03:51:41.737790Z","iopub.status.idle":"2021-09-23T03:51:41.750427Z","shell.execute_reply.started":"2021-09-23T03:51:41.737744Z","shell.execute_reply":"2021-09-23T03:51:41.749724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_img_path_3d(df, index, mri_type='FLAIR'):\n    patient_id = df['BraTS21ID'][index]\n    patient_path = df['path'][index]\n    modality_path = os.path.join(patient_path, mri_type)\n    total_img_num = df[f'{mri_type}_count'][index]\n    \n    files = sorted(glob.glob(f\"{modality_path}/*.dcm\"), \n                   key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])\n    \n    mid_num = total_img_num // 2\n    num_3d2 = config['num_3d'] // 2\n    start_idx = max(0, mid_num - num_3d2)\n    end_idx = min(len(files), mid_num + num_3d2)\n    \n    target_file_paths = files[start_idx:end_idx]\n    \n    return target_file_paths\n\n@tf.function\ndef preprocessing_img(img, threashold=5):\n    img = img - tf.math.reduce_mean(img)\n    img = img / tf.math.reduce_variance(img)\n    img = img - tf.math.reduce_min(img)\n    img = tf.where(img<threashold, img, threashold)\n    return img\n\n    \nclass ImageGenerator(tf.keras.utils.Sequence):\n    def __init__(self, df, mri_type='FLAIR'):\n        self.df = df\n        self.mri_type = mri_type\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, index):\n        paths = get_img_path_3d(self.df, index)\n        img_list = []\n        for path in paths:\n            dicom = pydicom.read_file(path)\n            img = dicom.pixel_array\n            img = np.expand_dims(img, -1)\n            #img = np.repeat(img, 3, axis=-1)\n            img = tf.convert_to_tensor(img, dtype=tf.float32)\n            img = tf.image.resize(img, [config['img_size'], config['img_size']])\n            img = tf.expand_dims(img, -2)\n            img_list.append(img)\n        img_3d = tf.concat(img_list, axis=-2)\n        return img_3d\n    \n    \ndef parse(x):\n    result = tf.io.parse_tensor(x, out_type=tf.float32)\n    result = tf.reshape(result, [config['img_size'], config['img_size'], config['num_3d'], 1])\n    return result\n\n\ndef build_3d_train_dataloader(train_df, p_fold=0):\n    p_train = train_df.query(f'fold != {p_fold}').reset_index(drop=True)\n    p_valid = train_df.query(f'fold == {p_fold}').reset_index(drop=True)\n\n    AUTOTUNE = tf.data.experimental.AUTOTUNE\n\n    train_datasets = []\n    for mode, df in zip(['train', 'valid'], [p_train, p_valid]):\n        i_g = ImageGenerator(df)\n        img_ds = tf.data.Dataset.from_generator(lambda: map(tuple, i_g),\n                                                output_types=(tf.float32),\n                                                output_shapes=(tf.TensorShape([config['img_size'], config['img_size'], config['num_3d'], 1])),\n                                                 )\n        \n        serial_ds = img_ds.map(tf.io.serialize_tensor)\n\n        if not os.path.exists(f'{mode}-{p_fold}-img.tfrec'):\n            img_tfrec = tf.data.experimental.TFRecordWriter(f'{mode}-{p_fold}-img.tfrec')\n            img_tfrec.write(serial_ds)\n        serial_ds = tf.data.TFRecordDataset(f'{mode}-{p_fold}-img.tfrec')\n        serial_ds = serial_ds.map(parse, num_parallel_calls=AUTOTUNE)\n\n        labels = df['MGMT_value']\n        label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(labels, tf.int32))\n\n        ds = tf.data.Dataset.zip((img_ds, label_ds))\n        \n        ds = ds.cache(filename=f'./cache.tf-{mode}-{p_fold}-data')\n        if mode == 'train':\n            train_count = len(df)\n            ds = ds.shuffle(buffer_size=train_count)\n        ds = ds.batch(config['batch_size'], drop_remainder=True)\n        ds = ds.prefetch(buffer_size=AUTOTUNE)\n        train_datasets.append(ds)\n\n    return train_datasets","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.752432Z","iopub.execute_input":"2021-09-23T03:51:41.753060Z","iopub.status.idle":"2021-09-23T03:51:41.771576Z","shell.execute_reply.started":"2021-09-23T03:51:41.753023Z","shell.execute_reply":"2021-09-23T03:51:41.770648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# TestDataset without Labels\ndef build_3d_test_dataloader(test_df):\n    AUTOTUNE = tf.data.experimental.AUTOTUNE\n\n    i_g = ImageGenerator(test_df)\n    img_ds = tf.data.Dataset.from_generator(lambda: map(tuple, i_g),\n                                         output_types=(tf.float32),\n                                         output_shapes=(tf.TensorShape([config['img_size'], config['img_size'], config['num_3d'], 1])),\n                                                 )\n    serial_ds = img_ds.map(tf.io.serialize_tensor)\n\n    if not os.path.exists('test-img.tfrec'):\n        img_tfrec = tf.data.experimental.TFRecordWriter('test-img.tfrec')\n        img_tfrec.write(serial_ds)\n    serial_ds = tf.data.TFRecordDataset('test-img.tfrec')\n    test_ds = serial_ds.map(parse, num_parallel_calls=AUTOTUNE)\n\n    test_ds = test_ds.cache(filename='./cache.tf-test-data')\n    test_ds = test_ds.batch(config['batch_size'], drop_remainder=False)\n    test_ds = test_ds.prefetch(buffer_size=AUTOTUNE)\n\n    return test_ds","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.772690Z","iopub.execute_input":"2021-09-23T03:51:41.773312Z","iopub.status.idle":"2021-09-23T03:51:41.785871Z","shell.execute_reply.started":"2021-09-23T03:51:41.773265Z","shell.execute_reply":"2021-09-23T03:51:41.785252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2021-09-23T03:51:41.786983Z","iopub.execute_input":"2021-09-23T03:51:41.787199Z","iopub.status.idle":"2021-09-23T03:51:41.801046Z","shell.execute_reply.started":"2021-09-23T03:51:41.787174Z","shell.execute_reply":"2021-09-23T03:51:41.800230Z"},"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-09-23T03:51:41.802386Z","iopub.execute_input":"2021-09-23T03:51:41.802588Z","iopub.status.idle":"2021-09-23T03:51:41.811425Z","shell.execute_reply.started":"2021-09-23T03:51:41.802565Z","shell.execute_reply":"2021-09-23T03:51:41.810652Z"},"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-09-23T03:51:41.812768Z","iopub.execute_input":"2021-09-23T03:51:41.812972Z","iopub.status.idle":"2021-09-23T03:51:46.365157Z","shell.execute_reply.started":"2021-09-23T03:51:41.812948Z","shell.execute_reply":"2021-09-23T03:51:46.364062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mri_types = ['FLAIR', 'T1w', 'T1wCE', 'T2w']\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.densenet import DenseNet121","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:46.367106Z","iopub.execute_input":"2021-09-23T03:51:46.367359Z","iopub.status.idle":"2021-09-23T03:51:47.811186Z","shell.execute_reply.started":"2021-09-23T03:51:46.367327Z","shell.execute_reply":"2021-09-23T03:51:47.810430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2021-09-23T03:51:47.812364Z","iopub.execute_input":"2021-09-23T03:51:47.812974Z","iopub.status.idle":"2021-09-23T03:51:48.498170Z","shell.execute_reply.started":"2021-09-23T03:51:47.812908Z","shell.execute_reply":"2021-09-23T03:51:48.497363Z"},"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":{"execution":{"iopub.status.busy":"2021-09-23T03:51:48.499364Z","iopub.execute_input":"2021-09-23T03:51:48.499598Z","iopub.status.idle":"2021-09-23T03:51:48.506306Z","shell.execute_reply.started":"2021-09-23T03:51:48.499570Z","shell.execute_reply":"2021-09-23T03:51:48.505426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:48.507839Z","iopub.execute_input":"2021-09-23T03:51:48.508087Z","iopub.status.idle":"2021-09-23T03:51:48.537845Z","shell.execute_reply.started":"2021-09-23T03:51:48.508057Z","shell.execute_reply":"2021-09-23T03:51:48.537220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)}","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:48.539049Z","iopub.execute_input":"2021-09-23T03:51:48.539470Z","iopub.status.idle":"2021-09-23T03:51:48.546457Z","shell.execute_reply.started":"2021-09-23T03:51:48.539438Z","shell.execute_reply":"2021-09-23T03:51:48.545837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model():\n    model = DenseNet121(spatial_dims=3, in_channels=1, out_channels=1)\n    return model    ","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:48.547577Z","iopub.execute_input":"2021-09-23T03:51:48.547973Z","iopub.status.idle":"2021-09-23T03:51:48.559751Z","shell.execute_reply.started":"2021-09-23T03:51:48.547944Z","shell.execute_reply":"2021-09-23T03:51:48.558852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modelfiles = ['FLAIR-e2-loss0.720-auc0.615.pth', 'T1w-e9-loss0.712-auc0.651.pth', 'T1wCE-e8-loss0.703-auc0.588.pth', 'T2w-e4-loss0.722-auc0.611.pth']\nprint(modelfiles)","metadata":{"execution":{"iopub.status.busy":"2021-09-23T03:51:48.560961Z","iopub.execute_input":"2021-09-23T03:51:48.561375Z","iopub.status.idle":"2021-09-23T03:51:48.571483Z","shell.execute_reply.started":"2021-09-23T03:51:48.561347Z","shell.execute_reply":"2021-09-23T03:51:48.570350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(modelfile, df, mri_type, split):\n    print(\"Predict:\", modelfile, 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    checkpoint = torch.load(f'../input/for-densenet/{modelfile}')\n    model.load_state_dict(checkpoint[\"model_state_dict\"])\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-09-23T03:51:48.572810Z","iopub.execute_input":"2021-09-23T03:51:48.573119Z","iopub.status.idle":"2021-09-23T03:51:48.584154Z","shell.execute_reply.started":"2021-09-23T03:51:48.573066Z","shell.execute_reply":"2021-09-23T03:51:48.583210Z"},"trusted":true},"execution_count":null,"outputs":[]}]}