{"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":"# try:\n#     import pylibjpeg\n# except:\n# Offline dependencies:\n!mkdir -p /root/.cache/torch/hub/checkpoints/\n!cp ../input/rsna2022whl/rsna-2022-whl/efficientnet_v2_s-dd5fe13b.pth  /root/.cache/torch/hub/checkpoints/\n\n!pip --no-cache-dir install /kaggle/input/rsna2022whl/rsna-2022-whl/{pydicom-2.3.0-py3-none-any.whl,pylibjpeg-1.4.0-py3-none-any.whl,python_gdcm-3.0.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl}\n!pip uninstall -y torch \n!pip uninstall -y torchvision\n!pip --no-cache-dir install /kaggle/input/rsna2022whl/rsna-2022-whl/{torch-1.12.1-cp37-cp37m-manylinux1_x86_64.whl,torchvision-0.13.1-cp37-cp37m-manylinux1_x86_64.whl}\n\n!mkdir -p /kaggle/temp/\n!cp -r /kaggle/input/verbebras-seg-whls/MedPy-0.4.0.tar.xyz /kaggle/temp/MedPy-0.4.0.tar.gz\n!pip --no-cache-dir install /kaggle/temp/MedPy-0.4.0.tar.gz\n!cp -r /kaggle/input/package1/p_tqdm-1.4.0.tar.xyz /kaggle/temp/p_tqdm-1.4.0.tar.gz\n!pip --no-cache-dir install /kaggle/temp/p_tqdm-1.4.0.tar.gz\n!pip --no-cache-dir install /kaggle/input/verbebras-seg-whls/{SimpleITK-2.0.2-cp37-cp37m-manylinux1_x86_64.whl,argparse-1.4.0-py2.py3-none-any.whl,batchgenerators-0.21-py3-none-any.whl,dicom2nifti-2.4.3-py3-none-any.whl,linecache2-1.0.0-py2.py3-none-any.whl,nnunet_customized-1.0-py3-none-any.whl,traceback2-1.4.0-py2.py3-none-any.whl,unittest2-1.1.0-py2.py3-none-any.whl,TotalSegmentator-1.3-py3-none-any.whl}\n# !pip install /kaggle/input/verbebras-seg-whls/batchgenerators-0.21-py3-none-any.whl \n# !pip install totalsegmentator==1.3\n                                            ","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:54:58.272229Z","iopub.execute_input":"2022-09-29T02:54:58.27318Z","iopub.status.idle":"2022-09-29T02:58:33.727115Z","shell.execute_reply.started":"2022-09-29T02:54:58.273074Z","shell.execute_reply":"2022-09-29T02:58:33.725892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\n!sudo rm -rf /root/.cache/pip/*\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:58:33.729706Z","iopub.execute_input":"2022-09-29T02:58:33.730093Z","iopub.status.idle":"2022-09-29T02:58:34.992993Z","shell.execute_reply.started":"2022-09-29T02:58:33.730049Z","shell.execute_reply":"2022-09-29T02:58:34.991941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nimport glob\nimport os\nimport re\n\nimport cv2\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport pydicom as dicom\nimport torch\nimport torchvision as tv\nfrom scipy import ndimage\n# from torch.cuda.amp import GradScaler, autocast\nfrom torchvision.models.feature_extraction import create_feature_extractor\nfrom tqdm.notebook import tqdm\n\n# Effnet\nWEIGHTS = tv.models.efficientnet.EfficientNet_V2_S_Weights.DEFAULT\nRSNA_2022_PATH = '../input/rsna-2022-cervical-spine-fracture-detection'\nTRAIN_IMAGES_PATH = f'{RSNA_2022_PATH}/train_images'\nTEST_IMAGES_PATH = f'{RSNA_2022_PATH}/test_images'\nEFFNET_CHECKPOINTS_PATH = '../input/effnetv2-models0927/effnetv2-models0927'\n\ntry:\n    from kaggle_secrets import UserSecretsClient\n    IS_KAGGLE = True\nexcept:\n    IS_KAGGLE = False\n\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:58:47.390392Z","iopub.execute_input":"2022-09-29T02:58:47.391203Z","iopub.status.idle":"2022-09-29T02:58:48.685313Z","shell.execute_reply.started":"2022-09-29T02:58:47.391162Z","shell.execute_reply":"2022-09-29T02:58:48.684196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_df_test():\n    df_test = pd.read_csv(f'{RSNA_2022_PATH}/test.csv')\n\n    if df_test.iloc[0].row_id == '1.2.826.0.1.3680043.10197_C1':\n        # test_images and test.csv are inconsistent in the dev dataset, fixing labels for the dev run.\n        df_test = pd.DataFrame({\n            \"row_id\": ['1.2.826.0.1.3680043.22327_C1', '1.2.826.0.1.3680043.25399_C1', '1.2.826.0.1.3680043.5876_C1'],\n            \"StudyInstanceUID\": ['1.2.826.0.1.3680043.22327', '1.2.826.0.1.3680043.25399', '1.2.826.0.1.3680043.5876'],\n            \"prediction_type\": [\"C1\", \"C1\", \"patient_overall\"]}\n        )\n    return df_test\n\ndf_test = load_df_test()\ndf_test","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:58:53.405845Z","iopub.execute_input":"2022-09-29T02:58:53.406563Z","iopub.status.idle":"2022-09-29T02:58:53.43648Z","shell.execute_reply.started":"2022-09-29T02:58:53.406502Z","shell.execute_reply":"2022-09-29T02:58:53.43541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_slices = glob.glob(f'{TEST_IMAGES_PATH}/*/*')\ntest_slices = [re.findall(f'{TEST_IMAGES_PATH}/(.*)/(.*).dcm', s)[0] for s in test_slices]\ndf_test_slices = pd.DataFrame(data=test_slices, columns=['StudyInstanceUID', 'Slice']).astype({'Slice': int}).sort_values(['StudyInstanceUID', 'Slice']).reset_index(drop=True)\ndf_test_slices","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:59:01.662102Z","iopub.execute_input":"2022-09-29T02:59:01.662591Z","iopub.status.idle":"2022-09-29T02:59:02.083683Z","shell.execute_reply.started":"2022-09-29T02:59:01.662507Z","shell.execute_reply":"2022-09-29T02:59:02.082693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import SimpleITK as sitk\n!cp -r /kaggle/input/vertebraesegmentation  /kaggle/working/","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:59:05.442192Z","iopub.execute_input":"2022-09-29T02:59:05.443252Z","iopub.status.idle":"2022-09-29T02:59:09.013496Z","shell.execute_reply.started":"2022-09-29T02:59:05.443209Z","shell.execute_reply":"2022-09-29T02:59:09.012031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from collections import OrderedDict\nfrom vertebraesegmentation.predict_v2 import predict_cases","metadata":{"execution":{"iopub.status.busy":"2022-09-29T05:51:15.229469Z","iopub.execute_input":"2022-09-29T05:51:15.23087Z","iopub.status.idle":"2022-09-29T05:51:15.341496Z","shell.execute_reply.started":"2022-09-29T05:51:15.230755Z","shell.execute_reply":"2022-09-29T05:51:15.339545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_case_from_list_of_files(data_itk, seg_file=None):\n    # assert isinstance(data_files, list) or isinstance(data_files, tuple), \"case must be either a list or a tuple\"\n    properties = OrderedDict()\n    data_npy = sitk.GetArrayFromImage(data_itk)\n    spacing = np.array(data_itk.GetSpacing())[[2, 1, 0]]\n    zoom = (1, spacing[1]/1.5, spacing[2]/1.5)\n    data_npy = ndimage.zoom(data_npy, zoom=zoom, order=1, mode='nearest')\n    properties[\"original_size_of_raw_data\"] = np.array(data_npy.shape)#[[2, 1, 0]]\n    properties[\"original_spacing\"] = np.array([spacing[0], 1.5, 1.5])#[[2, 1, 0]]\n#     properties[\"list_of_data_files\"] = data_files\n    properties[\"seg_file\"] = seg_file\n\n    properties[\"itk_origin\"] = data_itk.GetOrigin()\n    properties[\"itk_spacing\"] = np.array([spacing[0], 1.5, 1.5])[[1, 2, 0]]\n    properties[\"itk_direction\"] = np.array(data_itk.GetDirection())\n\n#     data_npy = sitk.GetArrayFromImage(data_itk)\n    if seg_file is not None:\n        seg_itk = sitk.ReadImage(seg_file)\n        seg_npy = sitk.GetArrayFromImage(seg_itk)[None].astype(np.float32)\n    else:\n        seg_npy = None\n    return [np.expand_dims(data_npy.astype(np.float32), 0), seg_npy, properties]\n\ndef save_nii(seg_old_size_postprocessed, properties_dict, out_fname):\n    \n    seg_resized_itk = sitk.GetImageFromArray(seg_old_size_postprocessed.astype(np.uint8))\n    seg_resized_itk.SetSpacing(properties_dict['itk_spacing'])\n    seg_resized_itk.SetOrigin(properties_dict['itk_origin'])\n    seg_resized_itk.SetDirection(properties_dict['itk_direction'])\n    sitk.WriteImage(seg_resized_itk, out_fname)\n\ndef normalize_image(image, max_hu=1300., min_hu=-100.):\n    image = (image - min_hu) / (max_hu - min_hu)\n    image[image > 1] = 0\n    image[image < 0] = 0\n    return (image * 255.).astype(np.int8)","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:59:09.56917Z","iopub.execute_input":"2022-09-29T02:59:09.569956Z","iopub.status.idle":"2022-09-29T02:59:09.583582Z","shell.execute_reply.started":"2022-09-29T02:59:09.569912Z","shell.execute_reply":"2022-09-29T02:59:09.581885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_model(model, name, path='.'):\n    data = torch.load(os.path.join(path, f'{name}.pth'), map_location=DEVICE)\n    model.load_state_dict(data)\n    return model\n\nclass EffnetModel(torch.nn.Module):\n    def __init__(self):\n        super().__init__()\n        effnet = tv.models.efficientnet_v2_s()\n        self.model = create_feature_extractor(effnet, ['flatten'])\n        self.nn_fracture = torch.nn.Sequential(\n            torch.nn.Linear(1280, 7),\n        )\n#         self.nn_vertebrae = torch.nn.Sequential(\n#             torch.nn.Linear(1280, 7),\n#         )\n\n    def forward(self, x):\n        # returns logits\n        x = self.model(x)['flatten']\n        return self.nn_fracture(x)#, self.nn_vertebrae(x)\n\n    def predict(self, x):\n        frac = self.forward(x)\n        return torch.sigmoid(frac)#, torch.sigmoid(vert)\n\n    \neffnet_model = load_model(EffnetModel(), 'effnetv2-f0_500_0.1615407603667743', EFFNET_CHECKPOINTS_PATH).to(DEVICE)\n# effnet_model.eval()","metadata":{"execution":{"iopub.status.busy":"2022-09-29T02:59:10.548135Z","iopub.execute_input":"2022-09-29T02:59:10.548604Z","iopub.status.idle":"2022-09-29T02:59:14.870176Z","shell.execute_reply.started":"2022-09-29T02:59:10.548554Z","shell.execute_reply":"2022-09-29T02:59:14.869099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_pids = os.listdir(f'{TEST_IMAGES_PATH}/')\nprint(test_pids)\n\nreader = sitk.ImageSeriesReader()\npredictions = []\nfor pid in test_pids:\n    dcm_files = f\"{TEST_IMAGES_PATH}/{pid}\"\n    dicom_names = reader.GetGDCMSeriesFileNames(dcm_files)\n    reader.SetFileNames(dicom_names)\n    itkimg = reader.Execute()\n        \n    # 颈椎分割\n    model_name = './vertebraesegmentation/model/model_final_checkpoint.model'\n    pkl_name = './vertebraesegmentation/model/model_final_checkpoint.model.pkl'\n    ppf_name = None\n\n    item = load_case_from_list_of_files(itkimg)\n    seg, properties_dict = predict_cases(model_name, pkl_name, ppf_name, item)\n    # save_nii(seg, properties_dict, f'./{pid}_vert.nii.gz')\n    \n    # 分类\n    img_numpy = sitk.GetArrayFromImage(itkimg)[::-1, ...]\n    img_numpy = normalize_image(img_numpy, max_hu=1300, min_hu=-100)\n    print(img_numpy.shape, seg.shape)\n    c1_c7_label = [24, 23, 22, 21, 20, 19, 18]\n    new_seg = np.zeros(seg.shape)\n    for ii in range(1, 8):\n        l = c1_c7_label[ii-1]\n        new_seg[seg==l] = ii\n    new_seg = np.array(new_seg[::-1, ...])   \n    preds = []\n    for index in range(img_numpy.shape[0]):\n        img = np.array(img_numpy[index, ...], dtype='uint8')\n        mask = np.array(new_seg[index, ...], dtype='uint8')\n        mask_unique = np.unique(mask)\n        ver_unique = []\n        for jj in mask_unique:\n            if jj > 0 and np.sum(mask==jj) > 30:\n                ver_unique.append(jj)\n      \n        if len(ver_unique) > 0:\n            img_ = cv2.resize(img, (384, 384))\n            mask_ = cv2.resize(mask, (384, 384), interpolation=cv2.INTER_NEAREST)\n            img = np.expand_dims(np.array(img_), axis=-1)\n            mask = np.expand_dims(np.array(mask_), axis=-1)\n            img = np.concatenate((img, img, mask*36), axis=-1)\n            img = np.transpose(img, (2, 0, 1)).astype(np.float64) / 255.\n#             print(img.shape, img.max(), img.min(), img.mean())\n            preprocess = WEIGHTS.transforms()\n            img_transformed = preprocess(torch.as_tensor(img)).unsqueeze(0)\n#             print(torch.max(img_transformed), torch.min(img_transformed))\n            ver_label = np.zeros(7).astype(np.int8)\n            for v in ver_unique:\n                ver_label[int(v-1)] = 1.\n\n            with torch.no_grad():\n                y = effnet_model.predict(img_transformed.to(DEVICE)).cpu().numpy()\n#             print(y)\n            pred = [pid, index+1]\n            pred.extend(y[0].tolist())\n            pred.extend(ver_label.tolist())\n        else:\n            pred = [pid, index+1, 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]\n        preds.append(pred)     \n    predictions.extend(preds)\n    \ndf_effnet_pred = pd.DataFrame(\n    data=predictions, columns=['StudyInstanceUID', 'Slice'] + [f'C{i}_effnet_frac' for i in range(1, 8)] + [f'C{i}_effnet_vert' for i in range(1, 8)])  ","metadata":{"execution":{"iopub.status.busy":"2022-09-29T03:02:04.800892Z","iopub.execute_input":"2022-09-29T03:02:04.801251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_sample_patient(df_pred):\n    patient = np.random.choice(df_pred.StudyInstanceUID)\n    df = df_pred.query('StudyInstanceUID == @patient').reset_index()\n\n    df[[f'C{i}_effnet_frac' for i in range(1, 8)]].plot(\n        title=f'Patient {patient}, fracture prediction',\n        ax=(plt.subplot(1, 2, 1)))\n\n    df[[f'C{i}_effnet_vert' for i in range(1, 8)]].plot(\n        title=f'Patient {patient}, vertebrae prediction',\n        ax=plt.subplot(1, 2, 2)\n    )\npd.set_option('display.max_rows', 1000)\npd.set_option('display.max_columns', 1000)\nplt.rcParams['figure.figsize'] = (20, 5)\nplot_sample_patient(df_effnet_pred)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# img2 = torch.randn(3, 224, 224) \n# img2 = img2 / img2.max()\n# print(img2.max(), img2.min())\n# preprocess = WEIGHTS.transforms()\n# batch = preprocess(img2).unsqueeze(0)\n# print(batch.max(), batch.min())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# df_effnet_pred.dtypes\nFRAC_COLS = [f'C{i}_effnet_frac' for i in range(1, 8)]\nVERT_COLS = [f'C{i}_effnet_vert' for i in range(1, 8)]\ndef patient_prediction(df):\n    c1c7 = np.average(df[FRAC_COLS].values, axis=0, weights=df[VERT_COLS].values)\n    pred_patient_overall = 1 - np.prod(1 - c1c7)\n    return pd.Series(data=np.concatenate([[pred_patient_overall], c1c7]), index=['patient_overall'] + [f'C{i}' for i in range(1, 8)])\n  \ndf_patient_pred = df_effnet_pred.groupby('StudyInstanceUID').apply(lambda df: patient_prediction(df))\ndf_patient_pred","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub = df_test.copy()\ndf_sub = df_sub.set_index('StudyInstanceUID').join(df_patient_pred)\ndf_sub['fractured'] = df_sub.apply(lambda r: r[r.prediction_type], axis=1)\ndf_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub[['row_id', 'fractured']].to_csv('submission.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}