{"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 pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport cv2\nimport torch\n\nimport os\nfrom tqdm.notebook import tqdm\nimport SimpleITK as sitk\n\nimport pydicom\nimport glob\nimport sys\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-10-08T01:59:34.591983Z","iopub.execute_input":"2021-10-08T01:59:34.592251Z","iopub.status.idle":"2021-10-08T01:59:39.750181Z","shell.execute_reply.started":"2021-10-08T01:59:34.592177Z","shell.execute_reply":"2021-10-08T01:59:39.749449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install ../input/segmentation-model-pt/pretrainedmodels-0.7.4/pretrainedmodels-0.7.4\n!pip install ../input/segmentation-model-pt/efficientnet_pytorch-0.6.3/efficientnet_pytorch-0.6.3/\n!pip install ../input/timm-pytorch-image-models/pytorch-image-models-master/\n\n!pip install ../input/segmentation-model-pt/segmentation_models_pytorch-0.2.0-py3-none-any.whl --no-index --no-deps\n","metadata":{"execution":{"iopub.status.busy":"2021-10-08T01:59:39.751883Z","iopub.execute_input":"2021-10-08T01:59:39.752157Z","iopub.status.idle":"2021-10-08T02:01:10.950075Z","shell.execute_reply.started":"2021-10-08T01:59:39.752123Z","shell.execute_reply":"2021-10-08T02:01:10.949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DICOM_IM_FOLDER = '../input/rsna-miccai-brain-tumor-radiogenomic-classification/test/'\nIM_FOLDER = '/test'\nDEVICE = 'cuda:0'\nN_WORKERS = 4\nSTRIDE = 5\nSEQ_LEN = 35\nLSTM_HIDDEN_SIZE = 128\nLSTM_LAYERS = 1\nMRI_TYPES = ['T1w', 'T1wCE', 'T2w', 'FLAIR']\n\nDIM = (224,224,3)\n\nSEG_BATCH_SIZE = 32\nCLF_BATCH_SIZE = 4\n\nFAST_SUB = True\n\nSEG_MODEL = {\n        'backbone_name':'densenet121',\n        'model_path':'../input/brain2dsegbest/Fold0_densenet121_2d_segment_v3.1_fix_pretrain_non_negative_ValidLoss0.078_ValidIOU0.855_Ep174.pth'\n    }\n\nCLF_CANDIDATES = [\n    {\n        'backbone_name':'eca_nfnet_l0',\n        'model_path':'../input/brain2dclflstm/FLAIR/FLAIR/Fold0_eca_nfnet_l0_2d_clf_v6_lstm_data_v5_ValidLoss0.593_ValidAUC0.617_Ep05.pth',\n        'mri_type':\"flair\"\n    },\n    {\n        'backbone_name':'eca_nfnet_l0',\n        'model_path':'../input/brain2dclflstm/T1w/T1w/Fold0_eca_nfnet_l0_2d_clf_v6_lstm_data_v5_ValidLoss0.662_ValidAUC0.642_Ep09.pth',\n        'mri_type':\"t1\"\n    },\n   {\n        'backbone_name':'eca_nfnet_l0',\n        'model_path':'../input/brain2dclflstm/T1wCE/T1wCE/Fold0_eca_nfnet_l0_2d_clf_v6_lstm_data_v5_ValidLoss0.684_ValidAUC0.555_Ep09.pth',\n        'mri_type':\"t1ce\"\n    },\n    {\n        'backbone_name':'eca_nfnet_l0',\n        'model_path':'../input/brain2dclflstm/T2w/T2w/Fold0_eca_nfnet_l0_2d_clf_v6_lstm_data_v5_ValidLoss0.604_ValidAUC0.523_Ep08.pth',\n        'mri_type':\"t2\"\n    },\n]","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:06:02.670017Z","iopub.execute_input":"2021-10-08T02:06:02.670672Z","iopub.status.idle":"2021-10-08T02:06:02.678469Z","shell.execute_reply.started":"2021-10-08T02:06:02.67063Z","shell.execute_reply":"2021-10-08T02:06:02.677465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from segmentation_models_pytorch.unetplusplus.model import UnetPlusPlus\nfrom segmentation_models_pytorch.losses import DiceLoss\nfrom segmentation_models_pytorch.utils.metrics import IoU","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:10.962559Z","iopub.execute_input":"2021-10-08T02:01:10.963246Z","iopub.status.idle":"2021-10-08T02:01:12.987897Z","shell.execute_reply.started":"2021-10-08T02:01:10.963208Z","shell.execute_reply":"2021-10-08T02:01:12.986998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_seg_model(candidate):\n    model = UnetPlusPlus(\n        encoder_name = candidate['backbone_name'],\n        encoder_depth = 5,\n        encoder_weights = None,\n        classes = 2,\n        activation = 'sigmoid',\n    )\n\n    weight_path = candidate.get('pretrained_weight')\n    if(weight_path is not None):\n        model.load_state_dict(torch.load(weight_path, map_location='cpu'))\n        \n    return model","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:13.010526Z","iopub.execute_input":"2021-10-08T02:01:13.010795Z","iopub.status.idle":"2021-10-08T02:01:13.01802Z","shell.execute_reply.started":"2021-10-08T02:01:13.010762Z","shell.execute_reply":"2021-10-08T02:01:13.016865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seg_model = get_seg_model(SEG_MODEL)\nseg_model.load_state_dict(torch.load(SEG_MODEL['model_path'], map_location='cpu'))\nseg_model.to(DEVICE)\n\nseg_model.eval()\nprint()","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:13.01927Z","iopub.execute_input":"2021-10-08T02:01:13.019705Z","iopub.status.idle":"2021-10-08T02:01:22.797511Z","shell.execute_reply.started":"2021-10-08T02:01:13.019668Z","shell.execute_reply":"2021-10-08T02:01:22.796732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\ndef get_transform(candidate, spatial_only=False):\n    dim = candidate.get('dim', DIM)\n    list_trans = [\n                A.Resize(width=int(dim[1]*1.2), height=int(dim[0]*1.2), always_apply=True),\n                A.CenterCrop(width=dim[1], height=dim[0], always_apply=True),\n                A.Normalize(), \n                ToTensorV2(p=1.0)\n    ]\n    return A.Compose(list_trans)\n\ndef get_inv_transform(original_w, original_h, candidate):\n    dim = candidate.get('dim', DIM)\n    list_trans = [\n                A.PadIfNeeded(min_height=int(dim[1]*1.2), min_width=int(dim[1]*1.2), always_apply=True),\n                A.Resize(width=original_w, height=original_h, always_apply=True),\n    ]\n    return A.Compose(list_trans)\n\ndef normalize_voxels(voxels):\n    _min = voxels.min()\n    _max = voxels.max()\n    new_voxels = (voxels - _min) / (_max-_min) * 255.0\n    return new_voxels\n\ndef check_empty(img, min_avg=0.1):\n    _mean = np.where(img>0, 1, 0).mean()\n    if(_mean > min_avg):\n        return True\n    return False","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:22.799075Z","iopub.execute_input":"2021-10-08T02:01:22.799498Z","iopub.status.idle":"2021-10-08T02:01:24.295932Z","shell.execute_reply.started":"2021-10-08T02:01:22.799458Z","shell.execute_reply":"2021-10-08T02:01:24.295117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def find_largest_countours(contours):\n    max_cnt = max(contours, key=lambda cnt: cv2.contourArea(cnt))\n    return max_cnt\n\ndef has_good_features(image, mask, area_mask_over_image_min_ratio=0.1, max_count_mask_contours=5):\n    _, image_thresh = cv2.threshold(image,1,255,cv2.THRESH_BINARY)\n    image_contours, _ = cv2.findContours(image=image_thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)\n    max_image_cnt = find_largest_countours(image_contours)\n    \n    _, mask_thresh = cv2.threshold(mask,0.5,1,cv2.THRESH_BINARY)\n    mask_contours, _ = cv2.findContours(image=mask_thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)\n    count_n_mask_contours = len(mask_contours)\n    if(count_n_mask_contours == 0):\n        return False\n    max_mask_cnt = find_largest_countours(mask_contours)\n    \n    area_mask_over_image_ratio = cv2.contourArea(max_mask_cnt) / cv2.contourArea(max_image_cnt)\n    \n    if(area_mask_over_image_ratio > area_mask_over_image_min_ratio \\\n       and count_n_mask_contours <= max_count_mask_contours):\n        return True\n    else:\n        return False","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:24.297652Z","iopub.execute_input":"2021-10-08T02:01:24.29804Z","iopub.status.idle":"2021-10-08T02:01:24.310399Z","shell.execute_reply.started":"2021-10-08T02:01:24.297999Z","shell.execute_reply":"2021-10-08T02:01:24.309619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def batch_predict_mask(data_loader, model):\n    batch_out = []\n    for batch_input in data_loader:\n        batch_input = batch_input.to(DEVICE)\n        batch_out.append(model(batch_input).cpu().detach().numpy())\n        \n    batch_out = np.concatenate(batch_out, axis=0)\n    batch_out = (batch_out > 0.5).astype('uint8')\n    \n    del batch_input\n    torch.cuda.empty_cache()\n    \n    return batch_out","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:24.312197Z","iopub.execute_input":"2021-10-08T02:01:24.313187Z","iopub.status.idle":"2021-10-08T02:01:24.323663Z","shell.execute_reply.started":"2021-10-08T02:01:24.313149Z","shell.execute_reply":"2021-10-08T02:01:24.3225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BrainSegmentationInferDataset(torch.utils.data.Dataset):\n    \n    def __init__(self, all_mri_voxels, transforms):\n        self.all_mri_voxels = all_mri_voxels\n        self.augmentations = transforms\n\n    def __len__(self):\n        return len(self.all_mri_voxels)\n\n    def __getitem__(self, index):\n        image = self.all_mri_voxels[index]\n        image = np.stack([image]*3, axis=-1)\n        \n        if self.augmentations:\n            augmented = self.augmentations(image=image)\n            image = augmented['image']\n        \n        return image\n\ndef error(e):\n    print(e)\n    \ndef read_and_preprocess_voxels_update(args):\n    if(args!=[]):\n        voxels, mri_type, images = args\n        global all_transformed_images, corresponding_mri_types, all_images\n        all_transformed_images += [image for image in voxels]\n        corresponding_mri_types += [mri_type]*len(voxels)\n        all_images += images\n\ndef read_and_preprocess_voxels(patient_id, mri_type, ext='.dcm'):\n    paths = glob.glob(os.path.join(DICOM_IM_FOLDER, patient_id, mri_type, '*'+ext))\n    paths = sorted(paths, key=lambda x: int(x.replace(ext,'').split(\"-\")[-1]))\n    positions = []\n    images = []\n\n    for path in paths:\n#         print(path)\n        img = pydicom.dcmread(str(path))\n        img = img.pixel_array\n#         img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n        if(check_empty(img)):\n            images.append(img)\n\n    if(len(images) == 0):\n        print(\"Found no images in case (patient_id, mri, path):\", patient_id, mri_type, paths)\n        return []\n\n    voxels = np.array(images)\n    voxels = normalize_voxels(voxels)  # normalize voxels to range(0,255)\n#     print(len(voxels))\n    return voxels, mri_type, list(voxels.astype('uint8'))\n        \n    \ndef sampling_one_image(patient_id, slice_index, image, out, mri_type):\n\n    mask_0, mask_1 = out[0], out[1]\n    inv_transforms = get_inv_transform(image.shape[1], image.shape[0], SEG_MODEL)\n    mask_0_original_size = inv_transforms(image=mask_0)['image']\n    mask_1_original_size = inv_transforms(image=mask_1)['image']\n\n    current_image_has_good_features = has_good_features(image, mask_0_original_size,\n                                                       area_mask_over_image_min_ratio=0.025)\n\n    if(not current_image_has_good_features):\n        return None\n\n    file_path = os.path.join(IM_FOLDER + '/2D_slice_data/', \n                                 f'BraTS2021_{patient_id}',\n                                 f'BraTS2021_{patient_id}_{mri_type}',\n                                f'BraTS2021_{patient_id}_{mri_type}_{slice_index:03d}')\n    os.makedirs(os.path.dirname(file_path), exist_ok=True)\n\n    mask_0_original_size *= 255  # convert to 255 scale\n    mask_1_original_size *= 255\n    _3channel_data = np.stack([image, mask_0_original_size, mask_1_original_size], axis=-1)\n#             print(_3channel_data.shape)\n#     cv2.imwrite(file_path, _3channel_data)\n    np.save(file_path, _3channel_data)\n\n#             plt.figure()\n#             plt.imshow(np.stack([_3channel_data[0], _3channel_data[1], _3channel_data[2]], axis=-1))\n#             plt.show()\n\n    return int(patient_id), mri_type, slice_index, file_path+'.npy'\n\n#         plt.figure(figsize=(10,10))\n#         plt.subplot(1,3,1)\n#         plt.imshow(image)\n#         plt.title('Has good feature: '+str(current_image_has_good_features))\n#         plt.subplot(1,3,2)\n#         plt.imshow(mask_0_original_size)\n#         plt.subplot(1,3,3)\n#         plt.imshow(mask_1_original_size)\n#         plt.show()\n\n\ndef sampling_one_image_update(args):\n    global list_patient_id, list_mri_type, list_slice_index, list_file_path\n    if(args is not None):\n        patient_id, mri_type, slice_index, file_path = args\n        list_patient_id.append(patient_id)\n        list_mri_type.append(mri_type)\n        list_slice_index.append(slice_index)\n        list_file_path.append(file_path)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:24.325615Z","iopub.execute_input":"2021-10-08T02:01:24.326156Z","iopub.status.idle":"2021-10-08T02:01:24.355336Z","shell.execute_reply.started":"2021-10-08T02:01:24.32605Z","shell.execute_reply":"2021-10-08T02:01:24.354433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import time\nfrom multiprocessing import Pool","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:24.35724Z","iopub.execute_input":"2021-10-08T02:01:24.357825Z","iopub.status.idle":"2021-10-08T02:01:24.367118Z","shell.execute_reply.started":"2021-10-08T02:01:24.357784Z","shell.execute_reply":"2021-10-08T02:01:24.366303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# paths = glob.glob(os.path.join(DICOM_IM_FOLDER, '00135', 'FLAIR', '*.dcm'))\n# paths = sorted(paths, key=lambda x: int(x.replace('.dcm','').split(\"-\")[-1]))\n\nif(FAST_SUB and len(os.listdir(DICOM_IM_FOLDER))==87):\n    iterations = ['00001', '00013', '00015']\nelse:\n    iterations = os.listdir(DICOM_IM_FOLDER)\n\nlist_patient_id = []\nlist_slice_index = []\nlist_mri_type = []\nlist_file_path = []\n\nos.makedirs(IM_FOLDER, exist_ok=True)\nfor patient_id in tqdm(iterations):\n    \n    s1 = time.time()\n    \n    all_transformed_images = []\n    corresponding_mri_types = []\n    all_images = []\n    \n    pool = Pool(processes=4)   \n\n    for mri_type in MRI_TYPES:\n        pool.apply_async(\n            read_and_preprocess_voxels,\n            args=(patient_id, mri_type),\n            callback=read_and_preprocess_voxels_update,\n            error_callback=error,\n        )\n\n    pool.close()\n    pool.join()    \n        \n#     print(len(all_transformed_images), len(corresponding_mri_types), len(all_images))\n    \n    e1 = time.time()\n    \n    s2 = time.time()\n    \n    transform = get_transform(SEG_MODEL)  # transform for segmentation input\n    seg_infer_ds = BrainSegmentationInferDataset(all_transformed_images, transform)\n    seg_infer_loader = torch.utils.data.DataLoader(seg_infer_ds, batch_size=SEG_BATCH_SIZE, shuffle=False,\n                        num_workers=N_WORKERS, pin_memory=torch.cuda.is_available())\n    batch_out = batch_predict_mask(seg_infer_loader, seg_model)\n    \n    e2 = time.time()\n    \n    s3 = time.time()\n\n    # sampling slices by mask area\n    pool = Pool(processes=8)   \n    \n    for i in range(len(all_images)):\n        image = all_images[i]\n        out = batch_out[i]\n        mri_type = corresponding_mri_types[i]\n        \n        pool.apply_async(\n            sampling_one_image,\n            args=(patient_id, i, image, out, mri_type),\n            callback=sampling_one_image_update,\n            error_callback=error,\n        )\n\n    pool.close()\n    pool.join()   \n    \n    del batch_out\n    torch.cuda.empty_cache()\n        \n    e3 = time.time()\n\n    print(f'Patial time: read time: {e1-s1}. mask pred time: {e2-s2}. sampling time: {e3-s3}')\n","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:01:24.369024Z","iopub.execute_input":"2021-10-08T02:01:24.369725Z","iopub.status.idle":"2021-10-08T02:02:05.862083Z","shell.execute_reply.started":"2021-10-08T02:01:24.369689Z","shell.execute_reply":"2021-10-08T02:02:05.861238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.DataFrame({\n    'BraTS21ID':list_patient_id,\n    'mri_type':list_mri_type,\n    'slice_index':list_slice_index,\n    'file_path':list_file_path,\n})","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:05.863557Z","iopub.execute_input":"2021-10-08T02:02:05.864172Z","iopub.status.idle":"2021-10-08T02:02:05.880144Z","shell.execute_reply.started":"2021-10-08T02:02:05.864126Z","shell.execute_reply":"2021-10-08T02:02:05.879328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.to_csv(os.path.join(IM_FOLDER, 'meta_classification.csv'), index=False)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:05.88141Z","iopub.execute_input":"2021-10-08T02:02:05.882143Z","iopub.status.idle":"2021-10-08T02:02:06.281969Z","shell.execute_reply.started":"2021-10-08T02:02:05.882107Z","shell.execute_reply":"2021-10-08T02:02:06.281157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ls /test/2D_slice_data","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:06.283619Z","iopub.execute_input":"2021-10-08T02:02:06.283981Z","iopub.status.idle":"2021-10-08T02:02:06.288429Z","shell.execute_reply.started":"2021-10-08T02:02:06.283945Z","shell.execute_reply":"2021-10-08T02:02:06.287552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def chunk_slices(list_files):\n    list_files = sorted(list_files)\n    chunks = []\n    n_chunks = max(int(np.ceil((len(list_files) - SEQ_LEN) / STRIDE ) + 1),1)\n    for i in range(n_chunks):\n        s = i*STRIDE\n        e = min(s+SEQ_LEN, len(list_files))\n        chunks.append(list_files[s:e])\n    return chunks\n\ndef expand(row):\n    list_files = row['chunk_file_paths']\n    return pd.DataFrame({\n        'BraTS21ID':[row['BraTS21ID']]*len(list_files),\n#         'MGMT_value':[row['MGMT_value']]*len(list_files),\n        'mri_type':[row['mri_type']]*len(list_files),\n        'file_path':list_files,\n#         'fold':[row['fold']]*len(list_files)\n    })\n\ndef get_first_value(df, col_name):\n    df[col_name] = df[col_name].map(lambda x: list(x)[0])\n    \ndef process_df_mri_type(df_mri):\n    df_mri_group = df_mri.groupby('BraTS21ID').agg(list)\n    df_mri_group = df_mri_group.reset_index()\n    df_mri_group['chunk_file_paths'] = df_mri_group.file_path.map(chunk_slices)\n    df_mri_group['chunk_count'] = df_mri_group['chunk_file_paths'].map(lambda x: len(x))\n    df_mri_group['chunk_cum_count'] = df_mri_group['chunk_count'].cumsum()\n    df_mri_group_expand = df_mri_group.apply(expand, axis=1).tolist()\n    df_mri_group_expand = pd.concat(df_mri_group_expand)\n\n#     for col_name in ['MGMT_value', 'mri_type', 'fold']:\n    for col_name in ['mri_type']:\n        get_first_value(df_mri_group_expand, col_name)\n        \n    return df_mri_group_expand","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:06.290212Z","iopub.execute_input":"2021-10-08T02:02:06.290522Z","iopub.status.idle":"2021-10-08T02:02:06.305514Z","shell.execute_reply.started":"2021-10-08T02:02:06.29049Z","shell.execute_reply":"2021-10-08T02:02:06.304642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BrainClassification2DDataset(torch.utils.data.Dataset):\n    \n    def __init__(self, csv, transforms=None):\n        self.csv = csv.reset_index(drop=True)\n        self.augmentations = transforms\n        \n        if('MGMT_value' not in self.csv.columns):\n            self.csv['MGMT_value'] = -1\n\n    def __len__(self):\n        return self.csv.shape[0]\n\n    def __getitem__(self, index):\n        row = self.csv.iloc[index]\n        list_file_path = row['file_path']\n        list_images = []\n        \n        label = row['MGMT_value']\n        for i, path in enumerate(list_file_path):\n            image = np.load(path)\n            label = row['MGMT_value']\n            list_images.append(image)\n                \n        images = np.stack(list_images, axis=0)\n        if(images.shape[0] < SEQ_LEN):\n            n_pad = SEQ_LEN - images.shape[0]\n            pad_matrix = np.zeros(shape=(n_pad, images.shape[1], images.shape[2], images.shape[3]))\n            images = np.concatenate([images, pad_matrix], axis=0)\n            \n        if self.augmentations:\n            images_dict = dict()\n            for i in range(len(images)):\n                if(i==0):\n                    images_dict['image'] = images[i]\n                else:\n                    images_dict[f'image{i-1}'] = images[i]\n            augmented = self.augmentations(**images_dict)\n            \n            transformed_images = []\n            for i in range(len(images)):\n                if(i==0):\n                    transformed_images.append(augmented['image'])\n                else:\n                    transformed_images.append(augmented[f'image{i-1}'])\n                    \n            transformed_images = np.stack(transformed_images, axis=0)\n            return transformed_images, torch.tensor(label)\n            \n        return images, torch.tensor(label)\n    \nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\ndef get_clf_transforms(candidate):\n    dim = candidate.get('dim', DIM)\n    additional_targets = {f'image{i}':'image' for i in range(SEQ_LEN-1)}\n    return A.Compose(\n        [\n            A.augmentations.geometric.transforms.Affine(scale=1.2, always_apply=True),\n            A.Resize(width=dim[1], height=dim[0], always_apply=True),\n            A.Normalize(),\n            ToTensorV2(p=1.0)\n        ],\n        additional_targets=additional_targets\n    )","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:06.307286Z","iopub.execute_input":"2021-10-08T02:02:06.307649Z","iopub.status.idle":"2021-10-08T02:02:06.331393Z","shell.execute_reply.started":"2021-10-08T02:02:06.307613Z","shell.execute_reply":"2021-10-08T02:02:06.330447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_flair = df[df.mri_type=='FLAIR']\ndf_t1 = df[df.mri_type=='T1w']\ndf_t1ce = df[df.mri_type=='T1wCE']\ndf_t2 = df[df.mri_type=='T2w']","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:06.333238Z","iopub.execute_input":"2021-10-08T02:02:06.333623Z","iopub.status.idle":"2021-10-08T02:02:06.350589Z","shell.execute_reply.started":"2021-10-08T02:02:06.333477Z","shell.execute_reply":"2021-10-08T02:02:06.349933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,7))\nplt.subplot(2,2,1)\nplt.boxplot(df_t1.BraTS21ID.value_counts())\nplt.title('t1')\nplt.subplot(2,2,2)\nplt.boxplot(df_t1ce.BraTS21ID.value_counts())\nplt.title('t1ce')\nplt.subplot(2,2,3)\nplt.boxplot(df_t2.BraTS21ID.value_counts())\nplt.title('t2')\nplt.subplot(2,2,4)\nplt.boxplot(df_flair.BraTS21ID.value_counts())\nplt.title('flair')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:06.352133Z","iopub.execute_input":"2021-10-08T02:02:06.35276Z","iopub.status.idle":"2021-10-08T02:02:06.804539Z","shell.execute_reply.started":"2021-10-08T02:02:06.352724Z","shell.execute_reply":"2021-10-08T02:02:06.803818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_t1_group_expand = process_df_mri_type(df_t1)\ndf_t1ce_group_expand = process_df_mri_type(df_t1ce)\ndf_t2_group_expand = process_df_mri_type(df_t2)\ndf_flair_group_expand = process_df_mri_type(df_flair)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:07.870793Z","iopub.execute_input":"2021-10-08T02:09:07.871384Z","iopub.status.idle":"2021-10-08T02:09:07.942881Z","shell.execute_reply.started":"2021-10-08T02:09:07.871346Z","shell.execute_reply":"2021-10-08T02:09:07.942239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"clf_candidate = CLF_CANDIDATES[0]\n\nds = BrainClassification2DDataset(df_t2_group_expand[df_t2_group_expand.BraTS21ID==13], get_clf_transforms(clf_candidate))","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:13:12.372355Z","iopub.execute_input":"2021-10-08T02:13:12.372642Z","iopub.status.idle":"2021-10-08T02:13:12.382567Z","shell.execute_reply.started":"2021-10-08T02:13:12.372613Z","shell.execute_reply":"2021-10-08T02:13:12.381577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, label = ds[0]","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:13:12.836633Z","iopub.execute_input":"2021-10-08T02:13:12.836927Z","iopub.status.idle":"2021-10-08T02:13:12.976121Z","shell.execute_reply.started":"2021-10-08T02:13:12.836867Z","shell.execute_reply":"2021-10-08T02:13:12.975322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for image in images:\n#     plt.figure(figsize=(10,3))\n#     plt.subplot(1,3,1)\n#     plt.imshow(image[0])\n#     plt.subplot(1,3,2)\n#     plt.imshow(image[1])\n#     plt.subplot(1,3,3)\n#     plt.imshow(image[2])","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:13:13.412387Z","iopub.execute_input":"2021-10-08T02:13:13.412648Z","iopub.status.idle":"2021-10-08T02:13:29.7632Z","shell.execute_reply.started":"2021-10-08T02:13:13.412621Z","shell.execute_reply":"2021-10-08T02:13:29.762312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # verìy image content\n# import SimpleITK as sitk\n\n# def visualize_3_planes_sitk(image):\n#     voxels = sitk.GetArrayFromImage(image)\n#     plt.figure(figsize=(9,3))\n#     plt.subplot(1,3,1)\n#     plt.imshow(voxels[voxels.shape[0]//2])\n#     plt.subplot(1,3,2)\n#     plt.imshow(voxels[:, voxels.shape[1]//2, :])\n#     plt.subplot(1,3,3)\n#     plt.imshow(voxels[:,:,voxels.shape[2]//2])","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:07.221263Z","iopub.execute_input":"2021-10-08T02:02:07.222064Z","iopub.status.idle":"2021-10-08T02:02:07.226908Z","shell.execute_reply.started":"2021-10-08T02:02:07.22203Z","shell.execute_reply":"2021-10-08T02:02:07.226053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# path = '../input/rsna-miccai-brain-tumor-radiogenomic-classification/test/00013/FLAIR'\n# reader = sitk.ImageSeriesReader()\n# filenamesDICOM = reader.GetGDCMSeriesFileNames(path)\n# reader.SetFileNames(filenamesDICOM)\n# voxels = reader.Execute()","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:07.228339Z","iopub.execute_input":"2021-10-08T02:02:07.228965Z","iopub.status.idle":"2021-10-08T02:02:07.235236Z","shell.execute_reply.started":"2021-10-08T02:02:07.228931Z","shell.execute_reply":"2021-10-08T02:02:07.23439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# visualize_3_planes_sitk(voxels)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:07.237086Z","iopub.execute_input":"2021-10-08T02:02:07.237438Z","iopub.status.idle":"2021-10-08T02:02:07.24293Z","shell.execute_reply.started":"2021-10-08T02:02:07.237403Z","shell.execute_reply":"2021-10-08T02:02:07.242119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def dfs_freeze(module):\n    for name, child in module.named_children():\n        for param in child.parameters():\n            param.requires_grad = False\n        dfs_freeze(child)\n        \ndef dfs_unfreeze(module):\n    for name, child in module.named_children():\n        for param in child.parameters():\n            param.requires_grad = True\n        dfs_unfreeze(child)\n\nimport timm\nfrom torch import nn\n\nclass BrainSequenceModel(nn.Module):\n    def __init__(self, backbone_name, backbone_pretrained,\n                 lstm_dim=64, lstm_layers=1, lstm_dropout=0., \n                 n_classes=1):\n        super(BrainSequenceModel, self).__init__()\n        self.backbone = timm.create_model(backbone_name, pretrained=False)\n        if(backbone_pretrained is not None):\n            self.backbone.load_state_dict(torch.load(backbone_pretrained))\n        \n        self.feature_extractor =  self.backbone.features\n        self.gap = self.backbone.global_pool\n        \n        lstm_inp_dim = self.backbone.classifier.in_features\n        \n        self.lstm = nn.LSTM(lstm_inp_dim, lstm_dim, num_layers=lstm_layers, \n                            batch_first=True, bidirectional=True,\n                            dropout=lstm_dropout)\n        \n        self.clf_head = nn.Linear(lstm_dim*2, n_classes)\n        \n    def forward(self, x):\n        n = x.shape[0]\n        seq_length = x.shape[1]\n        concat_x = torch.cat([x[i] for i in range(n)], axis=0)\n        concat_x = self.feature_extractor(concat_x)\n        concat_x = self.gap(concat_x)\n        \n        stacked_x = torch.stack([concat_x[i*seq_length:i*seq_length+seq_length] for i in range(n)], axis=0)\n        \n        seq_features, _ = self.lstm(stacked_x)\n        seq_features = seq_features[:, -1, :] # only get the last time step\n        \n        logits = self.clf_head(seq_features)\n        \n        return logits\n    \nclass BrainSequenceModelNFNet(nn.Module):\n    def __init__(self, backbone_name, backbone_pretrained,\n                 lstm_dim=64, lstm_layers=1, lstm_dropout=0., \n                 n_classes=1):\n        super(BrainSequenceModelNFNet, self).__init__()\n        self.backbone = timm.create_model(backbone_name, pretrained=False)\n        if(backbone_pretrained):\n            self.backbone.load_state_dict(torch.load(backbone_pretrained))\n        \n        lstm_inp_dim = self.backbone.head.fc.in_features\n        \n        self.backbone.head.fc = nn.Identity()\n        \n        self.lstm = nn.LSTM(lstm_inp_dim, lstm_dim, num_layers=lstm_layers, \n                            batch_first=True, bidirectional=True,\n                            dropout=lstm_dropout)\n        \n        self.clf_head = nn.Linear(lstm_dim*2*SEQ_LEN, n_classes)\n        \n    def forward(self, x):\n        n = x.shape[0]\n        seq_length = x.shape[1]\n        concat_x = torch.cat([x[i] for i in range(n)], axis=0)\n        concat_x = self.backbone(concat_x)\n        \n        \n        stacked_x = torch.stack([concat_x[i*seq_length:i*seq_length+seq_length] for i in range(n)], axis=0)\n        \n        seq_features, _ = self.lstm(stacked_x)\n        seq_features = seq_features.reshape(n,-1)\n        \n        logits = self.clf_head(seq_features)\n        \n        return logits\n    \ndef predict_fn(dataloader,model, scaler, device='cuda:0'):\n    '''Perform model training'''\n\n    model.eval()\n        \n    tk0 = tqdm(enumerate(dataloader), total=len(dataloader))\n    all_predictions = []\n    for i, batch in tk0:\n\n        # input, gt\n        voxels, labels = batch\n        voxels = voxels.to(device)\n        labels = labels.to(device).float()\n\n        # prediction\n        with torch.cuda.amp.autocast(), torch.no_grad():\n            logits = model(voxels)\n            logits = logits.view(-1)\n            probs = logits.sigmoid()\n       \n        all_predictions.append(probs.detach().cpu().numpy())\n        \n        del batch, voxels, labels, logits\n        torch.cuda.empty_cache()\n\n    all_predictions = np.concatenate(all_predictions)\n    \n    \n    return all_predictions","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:02:07.244861Z","iopub.execute_input":"2021-10-08T02:02:07.245268Z","iopub.status.idle":"2021-10-08T02:02:07.278787Z","shell.execute_reply.started":"2021-10-08T02:02:07.24523Z","shell.execute_reply":"2021-10-08T02:02:07.278093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = []\n\nfor clf_candidate in CLF_CANDIDATES:\n    mri_type = clf_candidate.get('mri_type')\n    if(mri_type == 't1'):\n        df_mri = df_t1_group_expand\n    elif(mri_type == 't1ce'):\n        df_mri = df_t1ce_group_expand\n    elif(mri_type == 't2'):\n        df_mri = df_t2_group_expand\n    elif(mri_type == 'flair'):\n        df_mri = df_flair_group_expand\n    \n    clf_batch_size = clf_candidate.get('batch_size', CLF_BATCH_SIZE)\n    test_ds = BrainClassification2DDataset(df_mri, get_clf_transforms(clf_candidate))\n    test_loader = torch.utils.data.DataLoader(test_ds, batch_size=clf_batch_size, shuffle=False,\n                            num_workers=N_WORKERS, pin_memory=torch.cuda.is_available())\n\n\n    # Model\n    if('nfnet' in clf_candidate['backbone_name'] ):\n        clf_model = BrainSequenceModelNFNet(clf_candidate['backbone_name'], clf_candidate.get('backbone_pretrained'),\n                                           lstm_dim=LSTM_HIDDEN_SIZE,lstm_layers=LSTM_LAYERS)\n    else:\n        clf_model = BrainSequenceModel(clf_candidate['backbone_name'], clf_candidate.get('backbone_pretrained'),\n                                      lstm_dim=LSTM_HIDDEN_SIZE,lstm_layers=LSTM_LAYERS)\n    clf_model.load_state_dict(torch.load(clf_candidate['model_path'], map_location='cpu'))\n    clf_model = clf_model.to(DEVICE)\n    print()\n    \n    scaler = torch.cuda.amp.GradScaler()\n        \n    test_prediction = predict_fn(test_loader, clf_model, scaler, DEVICE)\n    \n    tmp = df_mri.copy()\n    tmp['MGMT_value'] = test_prediction\n\n    tmp = tmp.groupby('BraTS21ID').agg({\n        'MGMT_value':lambda x:x.mean()\n    })\n    \n    sub_df.append(tmp)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:23.037351Z","iopub.execute_input":"2021-10-08T02:09:23.03763Z","iopub.status.idle":"2021-10-08T02:09:54.168808Z","shell.execute_reply.started":"2021-10-08T02:09:23.037602Z","shell.execute_reply":"2021-10-08T02:09:54.167722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.concat(sub_df, axis=1).mean(axis=1).reset_index()\nsub_df.columns = ['BraTS21ID', 'MGMT_value']\nsub_df","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:54.177526Z","iopub.execute_input":"2021-10-08T02:09:54.179448Z","iopub.status.idle":"2021-10-08T02:09:54.223131Z","shell.execute_reply.started":"2021-10-08T02:09:54.17937Z","shell.execute_reply":"2021-10-08T02:09:54.221047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub_df = pd.read_csv('../input/rsna-miccai-brain-tumor-radiogenomic-classification/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:54.224648Z","iopub.execute_input":"2021-10-08T02:09:54.225641Z","iopub.status.idle":"2021-10-08T02:09:54.241891Z","shell.execute_reply.started":"2021-10-08T02:09:54.225601Z","shell.execute_reply":"2021-10-08T02:09:54.239538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_sub = sample_sub_df[['BraTS21ID']].merge(sub_df, on='BraTS21ID', how='left').fillna(0.5)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:54.244049Z","iopub.execute_input":"2021-10-08T02:09:54.244872Z","iopub.status.idle":"2021-10-08T02:09:54.266809Z","shell.execute_reply.started":"2021-10-08T02:09:54.244835Z","shell.execute_reply":"2021-10-08T02:09:54.265985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_sub","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:54.268071Z","iopub.execute_input":"2021-10-08T02:09:54.268816Z","iopub.status.idle":"2021-10-08T02:09:54.298781Z","shell.execute_reply.started":"2021-10-08T02:09:54.268781Z","shell.execute_reply":"2021-10-08T02:09:54.297838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_sub.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-10-08T02:09:54.30031Z","iopub.execute_input":"2021-10-08T02:09:54.301042Z","iopub.status.idle":"2021-10-08T02:09:54.309723Z","shell.execute_reply.started":"2021-10-08T02:09:54.301007Z","shell.execute_reply":"2021-10-08T02:09:54.30857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}