{"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 pydicom\n\nimport pandas as pd\nimport numpy as np\n\nimport torch\nimport torchvision\nfrom torch import nn\nimport torch.nn.functional as F\nfrom torch import optim\nfrom torchvision import transforms\n\nfrom torch.utils.data import Dataset, DataLoader\n\nimport matplotlib.pyplot as plt\n\nfrom joblib import Parallel, delayed\nimport sys\n\nfrom tqdm import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-09-29T04:53:38.732518Z","iopub.execute_input":"2023-09-29T04:53:38.732863Z","iopub.status.idle":"2023-09-29T04:53:42.401245Z","shell.execute_reply.started":"2023-09-29T04:53:38.732837Z","shell.execute_reply":"2023-09-29T04:53:42.400227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SEED = 42\n\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:42.403148Z","iopub.execute_input":"2023-09-29T04:53:42.404258Z","iopub.status.idle":"2023-09-29T04:53:42.416883Z","shell.execute_reply.started":"2023-09-29T04:53:42.40422Z","shell.execute_reply":"2023-09-29T04:53:42.41592Z"},"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":"2023-09-29T04:53:42.418339Z","iopub.execute_input":"2023-09-29T04:53:42.419216Z","iopub.status.idle":"2023-09-29T04:53:42.500026Z","shell.execute_reply.started":"2023-09-29T04:53:42.419182Z","shell.execute_reply":"2023-09-29T04:53:42.498477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_ROOT = '/kaggle/input/rsna-2023-abdominal-trauma-detection/test_images'\nTEST_SERIES = '/kaggle/input/rsna-2023-abdominal-trauma-detection/test_series_meta.csv'\n\nVOLUME = (128, 64, 64)\n\nBATCH_SIZE = 32\n\nVOLUME = (128, 64, 64)\n\nWINDOW_STEP = 2\n# Odd Number Only\nWINDOW_WIDTH = 3\nPAD_ENDING = True\n\nSLICE_NUM = (128-1)//2 + 1\n\nTARGET_COLS  = [\n    \"bowel_injury\", \"extravasation_injury\",\n    \"kidney_healthy\", \"kidney_low\", \"kidney_high\",\n    \"liver_healthy\", \"liver_low\", \"liver_high\",\n    \"spleen_healthy\", \"spleen_low\", \"spleen_high\",\n]","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:42.503643Z","iopub.execute_input":"2023-09-29T04:53:42.504107Z","iopub.status.idle":"2023-09-29T04:53:42.511014Z","shell.execute_reply.started":"2023-09-29T04:53:42.504078Z","shell.execute_reply":"2023-09-29T04:53:42.509821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SLICE_NUM","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:42.512698Z","iopub.execute_input":"2023-09-29T04:53:42.513992Z","iopub.status.idle":"2023-09-29T04:53:42.522226Z","shell.execute_reply.started":"2023-09-29T04:53:42.513954Z","shell.execute_reply":"2023-09-29T04:53:42.521009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Net(nn.Module):\n    \n    def __init__(self):\n        \n        super(Net, self).__init__()\n        \n        resnet = torchvision.models.resnet18()\n        self.backbone = nn.Sequential(*list(resnet.children())[:-1])\n        \n        self.ltsm = nn.LSTM(input_size=512, hidden_size=128, batch_first=True)\n        self.fc = nn.Linear(in_features=128*SLICE_NUM, out_features=11)\n    \n    def forward(self, x):\n        \n        batch_size = x.shape[0]\n        x = x.view(batch_size * SLICE_NUM, WINDOW_WIDTH, VOLUME[1], VOLUME[2])\n        x = self.backbone(x)\n        x = x.view(batch_size, SLICE_NUM, -1) \n        \n        x, _ = self.ltsm(x)\n        x = torch.flatten(x, start_dim=1)\n        \n        x = self.fc(x)\n        \n        return x","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:42.523824Z","iopub.execute_input":"2023-09-29T04:53:42.52495Z","iopub.status.idle":"2023-09-29T04:53:42.534255Z","shell.execute_reply.started":"2023-09-29T04:53:42.524908Z","shell.execute_reply":"2023-09-29T04:53:42.533189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Net().to(device)\nsum(p.numel() for p in model.parameters() if p.requires_grad)","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:42.536136Z","iopub.execute_input":"2023-09-29T04:53:42.536877Z","iopub.status.idle":"2023-09-29T04:53:48.145189Z","shell.execute_reply.started":"2023-09-29T04:53:42.536841Z","shell.execute_reply":"2023-09-29T04:53:48.144162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_state_dict(torch.load('/kaggle/input/rsna-2-5d-resnet-ltsm/model.pt')['model'])\nmodel.eval()","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:48.146569Z","iopub.execute_input":"2023-09-29T04:53:48.147455Z","iopub.status.idle":"2023-09-29T04:53:48.901076Z","shell.execute_reply.started":"2023-09-29T04:53:48.14742Z","shell.execute_reply":"2023-09-29T04:53:48.900096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def dicom_to_image(dcm):\n    \n    pixel_array = dcm.pixel_array\n    \n    if dcm.PixelRepresentation == 1:\n        bit_shift = dcm.BitsAllocated - dcm.BitsStored\n        dtype = pixel_array.dtype \n        pixel_array = (pixel_array << bit_shift).astype(dtype) >>  bit_shift\n        \n    if dcm.PhotometricInterpretation == \"MONOCHROME1\":\n        pixel_array = 1 - pixel_array\n        \n    intercept = dcm.RescaleIntercept\n    slope = dcm.RescaleSlope\n    pixel_array = pixel_array * slope + intercept\n    \n    window_center = 50\n    window_width = 400\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    pixel_array = pixel_array.copy()\n    pixel_array[pixel_array < img_min] = img_min\n    pixel_array[pixel_array > img_max] = img_max\n    \n    pixel_array = (pixel_array - img_min)/(img_max-img_min)\n        \n    return pixel_array","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:48.902327Z","iopub.execute_input":"2023-09-29T04:53:48.90288Z","iopub.status.idle":"2023-09-29T04:53:48.9106Z","shell.execute_reply.started":"2023-09-29T04:53:48.902847Z","shell.execute_reply":"2023-09-29T04:53:48.909375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_dicom_image(entry):\n    path = os.path.join(TEST_ROOT, str(entry.patient_id), str(entry.series_id), str(entry.instance_id)+'.dcm')\n\n    dcm = pydicom.dcmread(path)\n\n    return dicom_to_image(dcm)","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:48.914606Z","iopub.execute_input":"2023-09-29T04:53:48.914884Z","iopub.status.idle":"2023-09-29T04:53:48.934289Z","shell.execute_reply.started":"2023-09-29T04:53:48.914855Z","shell.execute_reply":"2023-09-29T04:53:48.93322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_volume(instances):\n\n    instances = instances.sort_values('instance_id')\n\n    images = instances.apply(read_dicom_image, axis=1).values\n\n    images = np.stack(images)\n    images = torch.Tensor(images)\n\n    images = images.unsqueeze(dim=0).unsqueeze(dim=0)\n    images = F.interpolate(images, [VOLUME[0], VOLUME[1], VOLUME[2]]).squeeze()\n        \n    return images","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:53:48.935998Z","iopub.execute_input":"2023-09-29T04:53:48.936396Z","iopub.status.idle":"2023-09-29T04:53:48.946165Z","shell.execute_reply.started":"2023-09-29T04:53:48.936363Z","shell.execute_reply":"2023-09-29T04:53:48.945004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_series = pd.read_csv(TEST_SERIES)","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:11.533675Z","iopub.execute_input":"2023-09-29T04:54:11.534028Z","iopub.status.idle":"2023-09-29T04:54:11.542256Z","shell.execute_reply.started":"2023-09-29T04:54:11.533984Z","shell.execute_reply":"2023-09-29T04:54:11.541363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_instances(entry):\n    try:\n        patient_id = int(entry.patient_id)\n        series_id = int(entry.series_id)\n\n        path = os.path.join(TEST_ROOT, str(patient_id), str(series_id))\n        instances = os.listdir(path)\n        \n        instances = [int(instance[:-4]) for instance in instances if ((patient_id != 3124) or (series_id != 5842) or (int(instance[:-4]) != 514))]\n        n = len(instances)\n\n        data = pd.DataFrame({'patient_id' : n*[patient_id], 'series_id' : n*[series_id], 'instance_id' : instances})\n        \n        return data\n    except:\n        return None\n\ndf = test_series.apply(get_instances, axis=1)\ndf = pd.concat(df.values)\n\ndf.shape","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:12.050114Z","iopub.execute_input":"2023-09-29T04:54:12.050805Z","iopub.status.idle":"2023-09-29T04:54:12.078987Z","shell.execute_reply.started":"2023-09-29T04:54:12.050774Z","shell.execute_reply":"2023-09-29T04:54:12.078001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['group_by'] = df['patient_id'].astype(str) + '_' + df['series_id'].astype(str)\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:13.002529Z","iopub.execute_input":"2023-09-29T04:54:13.00286Z","iopub.status.idle":"2023-09-29T04:54:13.022335Z","shell.execute_reply.started":"2023-09-29T04:54:13.002831Z","shell.execute_reply":"2023-09-29T04:54:13.021389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestDataset(Dataset):\n    \n    def __init__(self, instances):\n        self.instances = instances\n        self.patient_ids = instances.patient_id.unique()\n    \n    def __len__(self):\n        return len(self.patient_ids)\n    \n    def get_slices(self, volume):\n        slices = []\n        \n        v = torch.flip(volume, dims=[0])\n        \n        margin = (WINDOW_WIDTH-1)//2\n        for i in range(margin, VOLUME[0], WINDOW_STEP):\n            if(i+margin < VOLUME[0]):\n                sl = v[(i-margin):(i+margin+1)]\n            else:\n                if(PAD_ENDING):\n                    sl = torch.zeros((WINDOW_WIDTH, VOLUME[1], VOLUME[2]))\n                    copy_number = VOLUME[0] - i + margin\n                    sl[:copy_number] = v[i-margin:VOLUME[0]]\n                else:\n                    break\n            sl = torch.flip(sl, dims=[0])\n            slices.append(sl)\n                    \n        return slices\n\n    def __getitem__(self, idx):\n        patient_id = self.patient_ids[idx]\n        instances = self.instances[self.instances.patient_id == patient_id]\n        \n        series_ids = instances.series_id.unique()\n#         print(series_ids)\n        series_slices = []\n        \n        for series_id in series_ids:\n            series_instances = instances[instances.series_id == series_id]\n#             print(series_instances.shape)\n            volume = get_volume(series_instances)\n#             print(volume.shape)\n            slices = self.get_slices(volume)\n#             print(len(slices))\n            slices = torch.stack(slices)\n            series_slices.append(slices)\n            \n        slices = torch.stack(series_slices)\n\n        return patient_id, slices","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:13.973544Z","iopub.execute_input":"2023-09-29T04:54:13.974226Z","iopub.status.idle":"2023-09-29T04:54:13.984281Z","shell.execute_reply.started":"2023-09-29T04:54:13.974194Z","shell.execute_reply":"2023-09-29T04:54:13.983103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = TestDataset(df)","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:16.353637Z","iopub.execute_input":"2023-09-29T04:54:16.354022Z","iopub.status.idle":"2023-09-29T04:54:16.361789Z","shell.execute_reply.started":"2023-09-29T04:54:16.353993Z","shell.execute_reply":"2023-09-29T04:54:16.360473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv('/kaggle/input/rsna-2023-abdominal-trauma-detection/sample_submission.csv')\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:17.378183Z","iopub.execute_input":"2023-09-29T04:54:17.37884Z","iopub.status.idle":"2023-09-29T04:54:17.40037Z","shell.execute_reply.started":"2023-09-29T04:54:17.378807Z","shell.execute_reply":"2023-09-29T04:54:17.399377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:17.626701Z","iopub.execute_input":"2023-09-29T04:54:17.627768Z","iopub.status.idle":"2023-09-29T04:54:17.632019Z","shell.execute_reply.started":"2023-09-29T04:54:17.627735Z","shell.execute_reply":"2023-09-29T04:54:17.630709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sig = nn.Sigmoid()\nsoft = nn.Softmax(dim=1)\n\nmodel.eval()\nwith torch.no_grad():\n    for patient_id, slices in test_dataset:\n        slices = slices.to(device)\n        logits = model(slices)\n        \n        logits[:,0:2] = sig(logits[:,0:2])\n        logits[:,2:5] = soft(logits[:,2:5])\n        logits[:,5:8] = soft(logits[:,5:8])\n        logits[:,8:11] = soft(logits[:,8:11])\n        \n        logits = torch.mean(logits, dim=0)\n\n        patient_filter = submission.patient_id == patient_id\n        submission.loc[patient_filter, TARGET_COLS] = logits.cpu().numpy()","metadata":{"execution":{"iopub.status.busy":"2023-09-29T04:54:17.874135Z","iopub.execute_input":"2023-09-29T04:54:17.874458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission['bowel_healthy'] = 1 - submission['bowel_injury']\nsubmission['extravasation_healthy'] = 1 - submission['extravasation_injury']\n\nsubmission.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.read_csv('submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}