{"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":"!pip install /kaggle/input/detectron2/omegaconf-2.0.6-py3-none-any.whl\n!pip install /kaggle/input/detectron2/iopath-0.1.8-py3-none-any.whl\n!pip install /kaggle/input/detectron2/fvcore-0.1.3.post20210317/fvcore-0.1.3.post20210317/\n!pip install /kaggle/input/detectron2/pycocotools-2.0.2/dist/pycocotools-2.0.2.tar\n!pip install /kaggle/input/detectron2/detectron2-0.4cu110-cp37-cp37m-linux_x86_64.whl","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:02:45.818529Z","iopub.execute_input":"2021-06-22T16:02:45.818879Z","iopub.status.idle":"2021-06-22T16:05:06.805116Z","shell.execute_reply.started":"2021-06-22T16:02:45.818832Z","shell.execute_reply":"2021-06-22T16:05:06.804119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom tqdm import tqdm\nfrom typing import Any, Dict, List\nfrom PIL import Image\n\nfrom detectron2 import model_zoo\nfrom detectron2.config import get_cfg\nfrom detectron2.engine import DefaultPredictor\nfrom detectron2.data import transforms as T\nfrom detectron2.modeling import build_model\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision\nfrom torchvision import models, transforms","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:06.808791Z","iopub.execute_input":"2021-06-22T16:05:06.809091Z","iopub.status.idle":"2021-06-22T16:05:07.327412Z","shell.execute_reply.started":"2021-06-22T16:05:06.809053Z","shell.execute_reply":"2021-06-22T16:05:07.326575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cfg = get_cfg()\nconfig_name = \"COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml\" \ncfg.merge_from_file(model_zoo.get_config_file(config_name))\ncfg.MODEL.ROI_HEADS.NUM_CLASSES = 3\ncfg.MODEL.WEIGHTS = '../input/covid-detectron2-training-resnet101/output/model_final.pth'\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5  # set the testing threshold for this model\n\npredictor = DefaultPredictor(cfg)","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:07.329131Z","iopub.execute_input":"2021-06-22T16:05:07.329488Z","iopub.status.idle":"2021-06-22T16:05:10.77529Z","shell.execute_reply.started":"2021-06-22T16:05:07.329453Z","shell.execute_reply":"2021-06-22T16:05:10.774393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_image_to_study_dict():\n    path = '../input/siim-covid19-detection/test'\n    image_to_study = {}\n    \n    for dirname, _, filenames in tqdm(os.walk(path)):\n        for file in filenames:\n            image_id = file.replace('.dcm', '')\n            study_id = dirname.split('/')[-2]\n            image_to_study[image_id] = study_id\n    \n    return image_to_study\n\ndef load_image_batch(test_dir, image_path_batch):\n    image_batch, image_shapes = [], []\n    resize_shape = (800, 800)\n    transform = [T.Resize(resize_shape)]\n    \n    for p in image_path_batch:\n        path = os.path.join(test_dir, p)\n        image = np.load(path)\n        height, width = image.shape\n        image_shapes.append(image.shape)\n        image, transforms = T.apply_transform_gens(transform, image)\n        image = np.expand_dims(image.astype('float32'), axis=0)\n        image = torch.from_numpy(image)\n        image_batch.append({'image': image, 'height': height, 'width': width})\n    \n    return image_batch","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:10.776981Z","iopub.execute_input":"2021-06-22T16:05:10.77734Z","iopub.status.idle":"2021-06-22T16:05:10.786144Z","shell.execute_reply.started":"2021-06-22T16:05:10.777303Z","shell.execute_reply":"2021-06-22T16:05:10.78483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def format_outputs(outputs):\n    preds = []    \n    for i, pred in enumerate(outputs):\n        instances = pred['instances']\n        fields: Dict[str, Any] = instances.get_fields()\n        pred_boxes = fields['pred_boxes'].tensor.cpu().numpy()\n        scores = fields['scores'].cpu().numpy()\n        pred_classes = fields['pred_classes'].cpu().numpy()\n        \n        predString = []\n        for box, score, class_id in zip(pred_boxes, scores, pred_classes):\n            xmin, ymin, xmax, ymax = box.astype(np.int32)\n            s = f'opacity {score:.6f} {xmin} {ymin} {xmax} {ymax}'\n            predString.append(s)\n        \n        if len(predString) == 0:\n            predString = 'none 1 0 0 1 1'\n        else:\n            predString = ' '.join(predString)        \n        preds.append(predString)\n        \n    return preds\n\n# def record_scores(outputs, image_path_batch, image_to_study, study_scores):\n#     for i, pred in enumerate(outputs):\n#         instances = pred['instances']\n#         fields: Dict[str, Any] = instances.get_fields()\n#         scores = fields['scores'].cpu().numpy()\n#         pred_classes = fields['pred_classes'].cpu().numpy()\n        \n#         image_id = image_path_batch[i][:-4]\n#         study_id = image_to_study[image_id]\n#         if study_id not in study_scores:\n#             study_scores[study_id] = [[] for _ in range(3)]\n        \n#         for score, class_id in zip(scores, pred_classes):\n#             study_scores[study_id][class_id].append(score)\n            \n# def format_study_scores(study_scores):\n#     thing_classes = [\"typical\", \"indeterminate\", \"atypical\"]\n#     study_preds = {'id': [], 'PredictionString': []}\n#     for study_id, scores in study_scores.items():\n#         predString = []\n#         for i, score in enumerate(scores):\n#             if len(score) != 0:\n#                 sc = np.mean(score)\n#                 class_name = thing_classes[i]\n#                 s = f'{class_name} {sc:.6f} 0 0 1 1'\n#                 predString.append(s)\n        \n#         if len(predString) == 0:\n#             predString = 'negative 1 0 0 1 1'\n#         else:\n#             predString = ' '.join(predString)\n        \n#         study_preds['id'].append(f'{study_id}_study')\n#         study_preds['PredictionString'].append(predString)\n    \n#     return study_preds","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:10.787571Z","iopub.execute_input":"2021-06-22T16:05:10.787913Z","iopub.status.idle":"2021-06-22T16:05:10.79846Z","shell.execute_reply.started":"2021-06-22T16:05:10.787878Z","shell.execute_reply":"2021-06-22T16:05:10.797547Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def add_private_entries(image_preds, study_preds):\n    image_ids = [_id.replace('_image', '') for _id in image_preds['id']]\n    study_ids = [_id.replace('_study', '') for _id in study_preds['id']]\n    public_images = set(image_ids)\n    public_studies = set(study_ids)\n    \n    path = '../input/siim-covid19-detection/test'\n    private_study_ids = set()\n    private_image_ids = set()\n    for dirname, _, filenames in tqdm(os.walk(path)):            \n        for file in filenames:\n            study_id = dirname.split('/')[-2]\n            image_id = file[:-4]\n            \n            if study_id not in public_studies:\n                private_study_ids.add(study_id)\n    \n            if image_id not in public_images:\n                private_image_ids.add(image_id)\n    \n    private_image_preds = {'id': [], 'PredictionString': []}\n    private_study_preds = {'id': [], 'PredictionString': []}\n    \n    for study_id in private_study_ids:\n        private_study_preds['id'].append(f'{study_id}_study')\n        private_study_preds['PredictionString'].append('negative 1 0 0 1 1')\n    \n    for image_id in private_image_ids:\n        private_image_preds['id'].append(f'{image_id}_image')\n        private_image_preds['PredictionString'].append('none 1 0 0 1 1')     \n        \n    preds = {\n        'id': image_preds['id'] + study_preds['id'] + private_image_preds['id'] + private_study_preds['id'],\n        'PredictionString':\n            image_preds['PredictionString'] + \\\n            study_preds['PredictionString'] + \\\n            private_image_preds['PredictionString'] + \\\n            private_study_preds['PredictionString']\n    }\n    return preds","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:10.799807Z","iopub.execute_input":"2021-06-22T16:05:10.800218Z","iopub.status.idle":"2021-06-22T16:05:10.812047Z","shell.execute_reply.started":"2021-06-22T16:05:10.80018Z","shell.execute_reply":"2021-06-22T16:05:10.811323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dir = '../input/covid-detectron2-test-set-preprocessing/test-npy'\nimage_paths = os.listdir(test_dir)\nbatch_size = 4\nimage_preds = {'id': [], 'PredictionString': []}","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:10.812989Z","iopub.execute_input":"2021-06-22T16:05:10.813353Z","iopub.status.idle":"2021-06-22T16:05:10.829382Z","shell.execute_reply.started":"2021-06-22T16:05:10.813316Z","shell.execute_reply":"2021-06-22T16:05:10.82841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in tqdm(range(0, len(image_paths), batch_size)):\n    if i + batch_size < len(image_paths):\n        image_path_batch = image_paths[i:i+batch_size]\n    else:\n        image_path_batch = image_paths[i:]\n    \n    image_batch = load_image_batch(test_dir, image_path_batch)\n    \n    with torch.no_grad():\n        outputs = predictor.model(image_batch)\n        \n    image_ids = [f'{p[:-4]}_image' for p in image_path_batch]\n    predStrings = format_outputs(outputs)\n    # record_scores(outputs, image_path_batch, image_to_study, study_scores)\n    image_preds['id'] += image_ids\n    image_preds['PredictionString'] += predStrings\n    \n# study_preds = format_study_scores(study_scores)","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:05:10.832686Z","iopub.execute_input":"2021-06-22T16:05:10.833082Z","iopub.status.idle":"2021-06-22T16:09:18.37727Z","shell.execute_reply.started":"2021-06-22T16:05:10.833047Z","shell.execute_reply":"2021-06-22T16:09:18.376113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Covid19Dataset(Dataset):\n    def __init__(self, root_dir, image_paths, transform):\n        self.root_dir = root_dir\n        self.image_paths = image_paths\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.image_paths)\n    \n    def __getitem__(self, idx):\n        path = os.path.join(self.root_dir, self.image_paths[idx])\n        data = np.load(path)\n        data = np.repeat(data[..., np.newaxis], 3, -1)\n        image = Image.fromarray(data)\n        image = self.transform(image)\n        image_id = self.image_paths[idx].split('.')[0]\n        \n        return image, image_id","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:09:18.378831Z","iopub.execute_input":"2021-06-22T16:09:18.379184Z","iopub.status.idle":"2021-06-22T16:09:18.38636Z","shell.execute_reply.started":"2021-06-22T16:09:18.379145Z","shell.execute_reply":"2021-06-22T16:09:18.3852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def initialize_model(num_classes):\n    model = models.resnet50(pretrained=False)\n    num_ftrs = model.fc.in_features\n    model.fc = nn.Linear(num_ftrs, num_classes)\n    return model\n\ndef record_scores(outputs, image_ids, image_to_study, study_scores):\n    \n    def softmax(x):\n        return np.exp(x) / np.sum(np.exp(x), axis=0)\n    \n    outputs = outputs.detach().cpu().numpy()\n    for output, image_id in zip(outputs, image_ids):\n        output = softmax(output)\n        study_id = image_to_study[image_id]\n        if study_id not in study_scores:\n            study_scores[study_id] = [[] for _ in range(4)]\n        for i in range(4):\n            study_scores[study_id][i].append(output[i])\n            \ndef format_study_scores(study_scores, threshold=0.5):\n    thing_classes = [\"negative\", \"typical\", \"indeterminate\", \"atypical\"]\n    study_preds = {'id': [], 'PredictionString': []}\n    \n    for study_id, scores in study_scores.items():\n        _id = study_id + '_study'\n        pred = []\n        scores = np.mean(scores, axis=1)\n        for i, score in enumerate(scores):\n            if score > threshold:\n                pred.append(f'{thing_classes[i]} {score:.6f} 0 0 1 1')\n        \n        if len(pred) == 0:\n            idx = np.argmax(scores)\n            pred.append(f'{thing_classes[idx]} {scores[idx]:.6f} 0 0 1 1')\n        \n        preds = ' '.join(pred)\n        study_preds['id'].append(_id)\n        study_preds['PredictionString'].append(preds)\n        \n    return study_preds","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:11:32.383447Z","iopub.execute_input":"2021-06-22T16:11:32.383793Z","iopub.status.idle":"2021-06-22T16:11:32.394642Z","shell.execute_reply.started":"2021-06-22T16:11:32.38376Z","shell.execute_reply":"2021-06-22T16:11:32.393516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes = 4\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nimage_to_study = get_image_to_study_dict()\ntransform = transforms.Compose([\n    transforms.Resize((800, 800)),\n    transforms.ToTensor(),\n])\n\ntest_dir = '../input/covid-detectron2-test-set-preprocessing/test-npy'\nimage_paths = os.listdir(test_dir)\ntest_set = Covid19Dataset(test_dir, image_paths, transform)\ntest_loader = DataLoader(test_set, batch_size=batch_size, shuffle=True)\nmodel = initialize_model(num_classes)\nmodel.load_state_dict(torch.load('../input/covid19-classification/resnet50.pt'))\nmodel = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:09:18.40285Z","iopub.execute_input":"2021-06-22T16:09:18.40338Z","iopub.status.idle":"2021-06-22T16:09:21.260414Z","shell.execute_reply.started":"2021-06-22T16:09:18.403335Z","shell.execute_reply":"2021-06-22T16:09:21.259537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\nstudy_scores = {}\nfor images, image_ids in tqdm(test_loader):\n    images = images.to(device)\n    outputs = model(images)\n    record_scores(outputs, image_ids, image_to_study, study_scores)\nstudy_preds = format_study_scores(study_scores)","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:11:59.017062Z","iopub.execute_input":"2021-06-22T16:11:59.017398Z","iopub.status.idle":"2021-06-22T16:16:50.944014Z","shell.execute_reply.started":"2021-06-22T16:11:59.017366Z","shell.execute_reply":"2021-06-22T16:16:50.939941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = add_private_entries(image_preds, study_preds)\nsub = pd.DataFrame(data=preds)\nsub","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:18:10.587565Z","iopub.execute_input":"2021-06-22T16:18:10.587898Z","iopub.status.idle":"2021-06-22T16:18:15.003027Z","shell.execute_reply.started":"2021-06-22T16:18:10.58786Z","shell.execute_reply":"2021-06-22T16:18:15.002126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2021-06-22T16:18:27.750097Z","iopub.execute_input":"2021-06-22T16:18:27.750424Z","iopub.status.idle":"2021-06-22T16:18:28.019055Z","shell.execute_reply.started":"2021-06-22T16:18:27.750393Z","shell.execute_reply":"2021-06-22T16:18:28.01821Z"},"trusted":true},"execution_count":null,"outputs":[]}]}