{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":80948,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":68023,"modelId":93182},{"sourceId":84684,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":71138,"modelId":96135}],"dockerImageVersionId":30746,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Credit\nCode has been adapted from the below link for this notebook:\nhttps://www.kaggle.com/code/itsuki9180/rsna2024-lsdc-submission-baseline ","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\n\nimport torch\nimport torch.nn.functional as F\nfrom torch import nn\nfrom torch.utils.data import DataLoader, Dataset\nimport torch.optim\nfrom torchvision import transforms\nimport albumentations as A\nimport glob\nimport re\nimport pydicom\nimport cv2","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-29T16:58:45.611400Z","iopub.execute_input":"2024-07-29T16:58:45.611838Z","iopub.status.idle":"2024-07-29T16:58:49.713935Z","shell.execute_reply.started":"2024-07-29T16:58:45.611805Z","shell.execute_reply":"2024-07-29T16:58:49.712986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = [512, 512]\nIN_CHANS = 10\nN_LABELS = 25\nN_CLASSES = 3 * N_LABELS\nrd = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/\"","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.716095Z","iopub.execute_input":"2024-07-29T16:58:49.716836Z","iopub.status.idle":"2024-07-29T16:58:49.722531Z","shell.execute_reply.started":"2024-07-29T16:58:49.716790Z","shell.execute_reply":"2024-07-29T16:58:49.721497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda:0') if torch.cuda.is_available() else torch.device('cpu')\ndevice","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.723905Z","iopub.execute_input":"2024-07-29T16:58:49.724321Z","iopub.status.idle":"2024-07-29T16:58:49.784585Z","shell.execute_reply.started":"2024-07-29T16:58:49.724283Z","shell.execute_reply":"2024-07-29T16:58:49.783313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/test_series_descriptions.csv\")\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.786097Z","iopub.execute_input":"2024-07-29T16:58:49.786999Z","iopub.status.idle":"2024-07-29T16:58:49.804831Z","shell.execute_reply.started":"2024-07-29T16:58:49.786951Z","shell.execute_reply":"2024-07-29T16:58:49.803668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_ids = list(df['study_id'].unique())\ndesc = list(df[\"series_description\"].unique())\nprint(study_ids)\nprint(desc)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.808361Z","iopub.execute_input":"2024-07-29T16:58:49.808687Z","iopub.status.idle":"2024-07-29T16:58:49.816525Z","shell.execute_reply.started":"2024-07-29T16:58:49.808659Z","shell.execute_reply":"2024-07-29T16:58:49.814676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.818526Z","iopub.execute_input":"2024-07-29T16:58:49.818859Z","iopub.status.idle":"2024-07-29T16:58:49.826571Z","shell.execute_reply.started":"2024-07-29T16:58:49.818828Z","shell.execute_reply":"2024-07-29T16:58:49.825549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABELS = list(sample_sub.columns)\nLABELS","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.827708Z","iopub.execute_input":"2024-07-29T16:58:49.828180Z","iopub.status.idle":"2024-07-29T16:58:49.837161Z","shell.execute_reply.started":"2024-07-29T16:58:49.828148Z","shell.execute_reply":"2024-07-29T16:58:49.836068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\n\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.838703Z","iopub.execute_input":"2024-07-29T16:58:49.838997Z","iopub.status.idle":"2024-07-29T16:58:49.846173Z","shell.execute_reply.started":"2024-07-29T16:58:49.838970Z","shell.execute_reply":"2024-07-29T16:58:49.845125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class RSNA24TestDataset(Dataset):\n    def __init__(self, df, study_ids, phase='test', transform=None):\n        self.df = df\n        self.study_ids = study_ids\n        self.transform = transform\n        self.phase = phase\n    \n    def __len__(self):\n        return len(self.study_ids)\n    \n    def get_img_paths(self, study_id, series_desc):\n        pdf = self.df[self.df['study_id']==study_id]\n        pdf_ = pdf[pdf['series_description']==series_desc]\n        allimgs = []\n        for i, row in pdf_.iterrows():\n            pimgs = glob.glob(f'{rd}/test_images/{study_id}/{row[\"series_id\"]}/*.dcm')\n            pimgs = sorted(pimgs, key=natural_keys)\n            allimgs.extend(pimgs)\n            \n        return allimgs\n    \n    def read_dcm_ret_arr(self, src_path):\n        dicom_data = pydicom.dcmread(src_path)\n        image = dicom_data.pixel_array\n        image = (image - image.min()) / (image.max() - image.min()) #+ 1e-6)# * 255\n        img = cv2.resize(image, (IMG_SIZE[0], IMG_SIZE[1]),interpolation=cv2.INTER_CUBIC)\n        assert img.shape==(IMG_SIZE[0], IMG_SIZE[1])\n        return img\n\n    def __getitem__(self, idx):\n        x = np.zeros((IMG_SIZE[0], IMG_SIZE[1], IN_CHANS), dtype=np.float64)\n        st_id = self.study_ids[idx]        \n        \n        # Sagittal T1\n        \"\"\"\n        NOT IMPLEMENTED\n        \"\"\"\n            \n        # Sagittal T2/STIR\n        allimgs_st2 = self.get_img_paths(st_id, 'Sagittal T2/STIR')\n        if len(allimgs_st2)==0:\n            #print(st_id, ': Sagittal T2/STIR, has no images')\n            for j, i in enumerate(np.arange(0, 10, 1)):\n                img = np.zeros((512,512))\n                x[..., j] = img.astype(np.float64)\n            \n        else:\n            step = len(allimgs_st2) / 10.0\n            st = len(allimgs_st2)/2.0 - 4.0*step\n            end = len(allimgs_st2)+0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                try:\n                    ind2 = max(0, int((i-0.5001).round()))\n                    img = self.read_dcm_ret_arr(allimgs_st2[ind2])\n                    x[..., j] = img.astype(np.float64)\n                except:\n                    print(f'failed to load on {st_id}, Sagittal T2/STIR')\n                    pass\n            \n        # Axial T2\n        \"\"\"\n        NOT IMPLEMENTED\n        \"\"\"\n            \n            \n        if self.transform is not None:\n            x = self.transform(image=x)['image']\n\n        x = x.transpose(2, 0, 1)\n                \n        return x, str(st_id)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.847545Z","iopub.execute_input":"2024-07-29T16:58:49.847827Z","iopub.status.idle":"2024-07-29T16:58:49.865282Z","shell.execute_reply.started":"2024-07-29T16:58:49.847803Z","shell.execute_reply":"2024-07-29T16:58:49.864285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transforms_test = A.Compose([\n    A.Resize(IMG_SIZE[0], IMG_SIZE[1]),\n    A.CenterCrop(384,384),\n    A.Resize(128,128)\n])","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.866547Z","iopub.execute_input":"2024-07-29T16:58:49.866933Z","iopub.status.idle":"2024-07-29T16:58:49.878699Z","shell.execute_reply.started":"2024-07-29T16:58:49.866906Z","shell.execute_reply":"2024-07-29T16:58:49.877717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = RSNA24TestDataset(df, study_ids, transform=transforms_test)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.879903Z","iopub.execute_input":"2024-07-29T16:58:49.880249Z","iopub.status.idle":"2024-07-29T16:58:49.888065Z","shell.execute_reply.started":"2024-07-29T16:58:49.880207Z","shell.execute_reply":"2024-07-29T16:58:49.887169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dl = DataLoader(test_ds, batch_size=1, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.889267Z","iopub.execute_input":"2024-07-29T16:58:49.889681Z","iopub.status.idle":"2024-07-29T16:58:49.899648Z","shell.execute_reply.started":"2024-07-29T16:58:49.889651Z","shell.execute_reply":"2024-07-29T16:58:49.898793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CNN_3D(nn.Module):\n    def __init__(self):\n        super(CNN_3D, self).__init__()\n        self.flatten = nn.Flatten()\n        self.block = nn.Sequential(\n            nn.Conv3d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=\"same\"),\n            nn.BatchNorm3d(32, affine=False),\n            nn.ReLU(),\n            nn.MaxPool3d(kernel_size=(1,2,2), stride=(1,2,2)),\n            nn.Conv3d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=\"same\"),\n            nn.BatchNorm3d(64, affine=False),\n            nn.ReLU(),\n            nn.MaxPool3d(kernel_size=(1,2,2), stride=(1,2,2)),\n            nn.Conv3d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=\"same\"),\n            nn.BatchNorm3d(128, affine=False),\n            nn.ReLU(),\n            nn.MaxPool3d(kernel_size=(1,2,2), stride=(1,2,2)),\n            nn.Conv3d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=\"same\"),\n            nn.BatchNorm3d(256, affine=False),\n            nn.ReLU(),\n            nn.MaxPool3d(kernel_size=(1,2,2), stride=(1,2,2)),\n            nn.Conv3d(in_channels=256, out_channels=512, kernel_size=3, stride=1, padding=\"same\"),\n            nn.BatchNorm3d(512, affine=False),\n            nn.ReLU(),\n            nn.MaxPool3d(kernel_size=(2,2,2), stride=(2,2,2))\n        )\n        self.linear1 = nn.Linear(5*4*4*512, out_features=256)\n        self.linear2 = nn.Linear(256, out_features=256)\n        self.linear3 = nn.Linear(256, out_features=256)\n        self.linear4 = nn.Linear(256, out_features=128)\n        self.linear5 = nn.Linear(128, out_features=75)\n\n    def forward(self, x):\n        out = self.block(x)\n        out = self.flatten(out)\n        out = self.linear1(out)\n        out = self.linear2(out)\n        out = self.linear3(out)\n        out = self.linear4(out)\n        out = self.linear5(out)\n        return out","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.901968Z","iopub.execute_input":"2024-07-29T16:58:49.902605Z","iopub.status.idle":"2024-07-29T16:58:49.917279Z","shell.execute_reply.started":"2024-07-29T16:58:49.902570Z","shell.execute_reply":"2024-07-29T16:58:49.916279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model=torch.load(\"/kaggle/input/t2stir3d_weights/pytorch/default/1/t2stir3d_weights.pt\")","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:49.921676Z","iopub.execute_input":"2024-07-29T16:58:49.922036Z","iopub.status.idle":"2024-07-29T16:58:50.144722Z","shell.execute_reply.started":"2024-07-29T16:58:49.922000Z","shell.execute_reply":"2024-07-29T16:58:50.143722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_predictions(model, test):\n    outputs = []\n    model.eval()\n    for i, data in enumerate(test_dl, 0):\n        inputs, study = data\n        inputs = torch.tensor(inputs, dtype=torch.float)\n        inputs = inputs.unsqueeze(0)\n        inputs = inputs.to(device)\n        with torch.no_grad():\n            output = model(inputs)\n            outputs.append(output)\n    return outputs","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:50.145896Z","iopub.execute_input":"2024-07-29T16:58:50.146218Z","iopub.status.idle":"2024-07-29T16:58:50.152917Z","shell.execute_reply.started":"2024-07-29T16:58:50.146188Z","shell.execute_reply":"2024-07-29T16:58:50.151941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = create_predictions(model, test_dl)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:50.154318Z","iopub.execute_input":"2024-07-29T16:58:50.154702Z","iopub.status.idle":"2024-07-29T16:58:51.577950Z","shell.execute_reply.started":"2024-07-29T16:58:50.154660Z","shell.execute_reply":"2024-07-29T16:58:51.576861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.579258Z","iopub.execute_input":"2024-07-29T16:58:51.579629Z","iopub.status.idle":"2024-07-29T16:58:51.854558Z","shell.execute_reply.started":"2024-07-29T16:58:51.579595Z","shell.execute_reply":"2024-07-29T16:58:51.853473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output_pred = []\nfor prediction in predictions:\n    o_pred = prediction.reshape(25, 3).softmax(1)\n    output_pred.append(o_pred)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.856145Z","iopub.execute_input":"2024-07-29T16:58:51.856517Z","iopub.status.idle":"2024-07-29T16:58:51.887165Z","shell.execute_reply.started":"2024-07-29T16:58:51.856490Z","shell.execute_reply":"2024-07-29T16:58:51.886406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for pred in output_pred:\n    print(pred.shape)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.888275Z","iopub.execute_input":"2024-07-29T16:58:51.888552Z","iopub.status.idle":"2024-07-29T16:58:51.893171Z","shell.execute_reply.started":"2024-07-29T16:58:51.888527Z","shell.execute_reply":"2024-07-29T16:58:51.892215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions_f = []\nfor prediction in output_pred:\n    prediction = prediction.to(\"cpu\")\n    predictions_f.append(prediction[torch.tensor([i for i in range(prediction.shape[0])])][:,torch.tensor([1,0,2])].numpy())\npredictions_f","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.894307Z","iopub.execute_input":"2024-07-29T16:58:51.894609Z","iopub.status.idle":"2024-07-29T16:58:51.909693Z","shell.execute_reply.started":"2024-07-29T16:58:51.894583Z","shell.execute_reply":"2024-07-29T16:58:51.908736Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_csv = pd.read_csv(rd+\"/train.csv\")\nsubmission_columns = training_csv.columns[1:]\nsubmission_columns","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.910924Z","iopub.execute_input":"2024-07-29T16:58:51.911219Z","iopub.status.idle":"2024-07-29T16:58:51.948823Z","shell.execute_reply.started":"2024-07-29T16:58:51.911187Z","shell.execute_reply":"2024-07-29T16:58:51.947941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_rows = []\nfor study in study_ids:\n    for condition in submission_columns:\n        new_c = condition.lower().replace(\"/\", \"_\")\n        submission_rows.append(str(study)+\"_\"+new_c)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.950025Z","iopub.execute_input":"2024-07-29T16:58:51.950343Z","iopub.status.idle":"2024-07-29T16:58:51.955425Z","shell.execute_reply.started":"2024-07-29T16:58:51.950317Z","shell.execute_reply":"2024-07-29T16:58:51.954455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_rows","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.956417Z","iopub.execute_input":"2024-07-29T16:58:51.956733Z","iopub.status.idle":"2024-07-29T16:58:51.968988Z","shell.execute_reply.started":"2024-07-29T16:58:51.956708Z","shell.execute_reply":"2024-07-29T16:58:51.968071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = pd.DataFrame()\nsubmission_df[LABELS[0]] = submission_rows","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.970156Z","iopub.execute_input":"2024-07-29T16:58:51.970491Z","iopub.status.idle":"2024-07-29T16:58:51.980587Z","shell.execute_reply.started":"2024-07-29T16:58:51.970466Z","shell.execute_reply":"2024-07-29T16:58:51.979691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds_df = pd.DataFrame(columns=LABELS[1:4])\nfor pred in predictions_f:\n    pred = pd.DataFrame(pred, columns=LABELS[1:4])\n    preds_df = pd.concat([preds_df, pred], axis=0, ignore_index=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.981715Z","iopub.execute_input":"2024-07-29T16:58:51.982668Z","iopub.status.idle":"2024-07-29T16:58:51.993516Z","shell.execute_reply.started":"2024-07-29T16:58:51.982633Z","shell.execute_reply":"2024-07-29T16:58:51.992561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_submission = pd.concat([submission_df, preds_df], axis=1)\nfinal_submission = final_submission.sort_values(by=\"row_id\")","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:51.995431Z","iopub.execute_input":"2024-07-29T16:58:51.995721Z","iopub.status.idle":"2024-07-29T16:58:52.006098Z","shell.execute_reply.started":"2024-07-29T16:58:51.995698Z","shell.execute_reply":"2024-07-29T16:58:52.005060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_submission.to_csv(\"submission.csv\", index=False)\npd.read_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-07-29T16:58:52.007411Z","iopub.execute_input":"2024-07-29T16:58:52.007823Z","iopub.status.idle":"2024-07-29T16:58:52.034284Z","shell.execute_reply.started":"2024-07-29T16:58:52.007789Z","shell.execute_reply":"2024-07-29T16:58:52.033213Z"},"trusted":true},"execution_count":null,"outputs":[]}]}