{"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 numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport matplotlib.patches as patches\nimport seaborn as sns\nsns.set(style='darkgrid', font_scale=1.6)\nimport cv2\nimport os\nfrom os import listdir\nimport re\nimport gc\nimport sys\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom tqdm import tqdm\nfrom pprint import pprint\nfrom time import time\nimport itertools\nfrom skimage import measure \nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\nimport nibabel as nib\nfrom glob import glob\n\nfrom sklearn.model_selection import train_test_split, StratifiedGroupKFold, GroupKFold\nfrom sklearn.metrics import confusion_matrix, accuracy_score\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras import callbacks\n\n# Models\nfrom sklearn.linear_model import LinearRegression, LogisticRegression\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.svm import SVC\nfrom sklearn.tree import DecisionTreeClassifier\nfrom sklearn.ensemble import RandomForestClassifier\nfrom xgboost import XGBClassifier\nfrom lightgbm import LGBMClassifier\nfrom catboost import CatBoostClassifier\nfrom sklearn.naive_bayes import GaussianNB","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-11-28T12:55:43.02959Z","iopub.execute_input":"2022-11-28T12:55:43.030617Z","iopub.status.idle":"2022-11-28T12:55:53.009526Z","shell.execute_reply.started":"2022-11-28T12:55:43.030564Z","shell.execute_reply":"2022-11-28T12:55:53.007799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load dataframes\ntrain_df = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/train.csv\")\ntrain_bbox = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/train_bounding_boxes.csv\")\ntest_df = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/test.csv\")\nss = pd.read_csv(\"../input/rsna-2022-cervical-spine-fracture-detection/sample_submission.csv\")\n\n# Print dataframe shapes\nprint('train shape:', train_df.shape)\nprint('train bbox shape:', train_bbox.shape)\nprint('test shape:', test_df.shape)\nprint('ss shape:', ss.shape)\nprint('')\n\n# Show first few entries\ntrain_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:55:53.012177Z","iopub.execute_input":"2022-11-28T12:55:53.012637Z","iopub.status.idle":"2022-11-28T12:55:53.08737Z","shell.execute_reply.started":"2022-11-28T12:55:53.012591Z","shell.execute_reply":"2022-11-28T12:55:53.085941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Create segmentation df**","metadata":{}},{"cell_type":"code","source":"# Store segmentation paths in a dataframe\nbase_path = \"../input/rsna-2022-cervical-spine-fracture-detection\"\nseg_paths = glob(f\"{base_path}/segmentations/*\")\nseg_df = pd.DataFrame({'path': seg_paths})\nseg_df['StudyInstanceUID'] = seg_df['path'].apply(lambda x:x.split('/')[-1][:-4])\nseg_df = seg_df[['StudyInstanceUID','path']]\nprint('seg_df shape:', seg_df.shape)\nseg_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:55:53.088952Z","iopub.execute_input":"2022-11-28T12:55:53.089346Z","iopub.status.idle":"2022-11-28T12:55:53.149548Z","shell.execute_reply.started":"2022-11-28T12:55:53.089308Z","shell.execute_reply":"2022-11-28T12:55:53.148364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Metadata was extracted previously (check out my RSNA dataset)\nmeta_train = pd.read_csv(\"../input/rsna-2022-spine-fracture-detection-metadata/meta_train_clean.csv\")\n\n# Only select patients with segmentations\nmeta_seg = meta_train[meta_train['StudyInstanceUID'].isin(seg_df['StudyInstanceUID'])].reset_index(drop=True)\nprint('meta_seg shape:', meta_seg.shape)\nmeta_seg.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:55:53.152879Z","iopub.execute_input":"2022-11-28T12:55:53.153264Z","iopub.status.idle":"2022-11-28T12:55:54.592558Z","shell.execute_reply.started":"2022-11-28T12:55:53.153229Z","shell.execute_reply":"2022-11-28T12:55:54.59129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Example\nex_path = \"../input/rsna-2022-cervical-spine-fracture-detection/segmentations/1.2.826.0.1.3680043.12281.nii\"\nexample = nib.load(ex_path)\nexample = example.get_fdata()  # convert to numpy array\nexample = example[:, ::-1, ::-1].transpose(2, 1, 0)  # align orientation with train image\nnp.unique(example[240])","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:55:54.594439Z","iopub.execute_input":"2022-11-28T12:55:54.595962Z","iopub.status.idle":"2022-11-28T12:55:56.125251Z","shell.execute_reply.started":"2022-11-28T12:55:54.595896Z","shell.execute_reply":"2022-11-28T12:55:56.123972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure()\nplt.imshow(example[240])\nplt.title('Segmentation example')\nplt.colorbar()\nplt.axis('off')\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-11-28T12:55:56.126968Z","iopub.execute_input":"2022-11-28T12:55:56.128144Z","iopub.status.idle":"2022-11-28T12:55:56.381342Z","shell.execute_reply.started":"2022-11-28T12:55:56.128049Z","shell.execute_reply":"2022-11-28T12:55:56.379876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Initialise targets\ntargets = ['C1','C2','C3','C4','C5','C6','C7']\nmeta_seg[targets]=0","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:55:56.383018Z","iopub.execute_input":"2022-11-28T12:55:56.383448Z","iopub.status.idle":"2022-11-28T12:55:56.3956Z","shell.execute_reply.started":"2022-11-28T12:55:56.383406Z","shell.execute_reply":"2022-11-28T12:55:56.39404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_seg = pd.read_csv('../input/rsna-2022-spine-fracture-detection-metadata/meta_segmentation.csv')\nmeta_seg.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:56:02.247181Z","iopub.execute_input":"2022-11-28T12:56:02.247705Z","iopub.status.idle":"2022-11-28T12:56:02.33489Z","shell.execute_reply.started":"2022-11-28T12:56:02.247655Z","shell.execute_reply":"2022-11-28T12:56:02.333434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Examples**","metadata":{}},{"cell_type":"code","source":"meta_seg[['StudyInstanceUID','Slice']+targets].iloc[199:204,:]","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:56:03.286054Z","iopub.execute_input":"2022-11-28T12:56:03.286561Z","iopub.status.idle":"2022-11-28T12:56:03.305991Z","shell.execute_reply.started":"2022-11-28T12:56:03.286521Z","shell.execute_reply":"2022-11-28T12:56:03.304568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('UID:', meta_seg['StudyInstanceUID'].unique()[0])\npd.set_option('display.max_rows', 500)\nmeta_seg[meta_seg['StudyInstanceUID']==meta_seg['StudyInstanceUID'].unique()[0]].loc[110:340,targets]","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-11-28T12:56:04.166975Z","iopub.execute_input":"2022-11-28T12:56:04.167448Z","iopub.status.idle":"2022-11-28T12:56:04.223994Z","shell.execute_reply.started":"2022-11-28T12:56:04.167408Z","shell.execute_reply":"2022-11-28T12:56:04.222423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"slice_max_seg = meta_seg.groupby('StudyInstanceUID')['Slice'].max().to_dict()\nmeta_seg['SliceRatio'] = 0\nmeta_seg['SliceRatio'] = meta_seg['Slice']/meta_seg['StudyInstanceUID'].map(slice_max_seg)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:56:06.095017Z","iopub.execute_input":"2022-11-28T12:56:06.095576Z","iopub.status.idle":"2022-11-28T12:56:06.115901Z","shell.execute_reply.started":"2022-11-28T12:56:06.095523Z","shell.execute_reply":"2022-11-28T12:56:06.114745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"features = ['SliceRatio','SliceThickness','ImagePositionPatient_x','ImagePositionPatient_y','ImagePositionPatient_z']\n\n# Features and targets\nX = meta_seg[['StudyInstanceUID']+features]\ny = meta_seg[targets]","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:56:06.509035Z","iopub.execute_input":"2022-11-28T12:56:06.509561Z","iopub.status.idle":"2022-11-28T12:56:06.522413Z","shell.execute_reply.started":"2022-11-28T12:56:06.509492Z","shell.execute_reply":"2022-11-28T12:56:06.521031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gkf = GroupKFold(n_splits=5)\n(train_idx, valid_idx) = next(gkf.split(X, y, groups = X['StudyInstanceUID']))\n\nX_train, y_train = X.iloc[train_idx,:], y.iloc[train_idx,:]\n\nX_valid, y_valid = X.iloc[valid_idx,:], y.iloc[valid_idx,:]\n\nX_train = X_train.drop('StudyInstanceUID', axis=1)\nX_valid = X_valid.drop('StudyInstanceUID', axis=1)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:56:06.951654Z","iopub.execute_input":"2022-11-28T12:56:06.952146Z","iopub.status.idle":"2022-11-28T12:56:06.985757Z","shell.execute_reply.started":"2022-11-28T12:56:06.952102Z","shell.execute_reply":"2022-11-28T12:56:06.984474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train classifier\nclf = RandomForestClassifier()\nclf.fit(X_train, y_train)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train","metadata":{"execution":{"iopub.status.busy":"2022-11-28T12:56:44.658906Z","iopub.execute_input":"2022-11-28T12:56:44.659385Z","iopub.status.idle":"2022-11-28T12:56:44.682853Z","shell.execute_reply.started":"2022-11-28T12:56:44.659342Z","shell.execute_reply":"2022-11-28T12:56:44.681481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate model\ny_preds = clf.predict(X_valid)\n\ntotal_acc = 0 \nfor i in range(7):\n    acc = (y_valid[f'C{i+1}']==y_preds[:,i]).sum()/len(y_preds[:,i])\n    total_acc+=acc/7\n    print(f'Accuracy of C{i+1}: {acc} %')\n\nprint('')\nprint(f'Overall accuracy: {total_acc} %')","metadata":{"execution":{"iopub.status.busy":"2022-11-28T11:30:45.053213Z","iopub.execute_input":"2022-11-28T11:30:45.053746Z","iopub.status.idle":"2022-11-28T11:30:45.451212Z","shell.execute_reply.started":"2022-11-28T11:30:45.053696Z","shell.execute_reply":"2022-11-28T11:30:45.449879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Feature importances\npd.DataFrame({'Feature':features, 'Importance':clf.feature_importances_}).sort_values(by='Importance', ascending=False)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T11:30:45.452879Z","iopub.execute_input":"2022-11-28T11:30:45.453264Z","iopub.status.idle":"2022-11-28T11:30:45.484299Z","shell.execute_reply.started":"2022-11-28T11:30:45.45323Z","shell.execute_reply":"2022-11-28T11:30:45.482963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = clf.predict(X_valid)\n\n# Confusion matrices\nfig = plt.figure(figsize=(20,10))\nfor i in range(7):\n    cm = confusion_matrix(preds[:,i], y_valid.values[:,i])\n    plt.subplot(2,4,i+1)\n    CBAR=False\n    if (i==3) or (i==6):\n        CBAR=True\n    sns.heatmap(cm, annot=True, fmt='d', cbar=CBAR, cmap='Blues')\n    plt.xlabel('Predicted label')\n    plt.ylabel('True label')\n    plt.title(f'C{i+1}')\nfig.tight_layout()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-11-28T11:30:45.485934Z","iopub.execute_input":"2022-11-28T11:30:45.486288Z","iopub.status.idle":"2022-11-28T11:30:47.290033Z","shell.execute_reply.started":"2022-11-28T11:30:45.486256Z","shell.execute_reply":"2022-11-28T11:30:47.288988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Example of predictions**","metadata":{}},{"cell_type":"code","source":"np.set_printoptions(threshold=np.inf)\nclf.predict(X.drop('StudyInstanceUID',axis=1))[110:250,:]","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-11-28T11:30:47.29103Z","iopub.execute_input":"2022-11-28T11:30:47.291341Z","iopub.status.idle":"2022-11-28T11:30:49.067563Z","shell.execute_reply.started":"2022-11-28T11:30:47.291312Z","shell.execute_reply":"2022-11-28T11:30:49.066299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read in metadata for entire train set\nmeta_train = pd.read_csv('../input/rsna-2022-spine-fracture-detection-metadata/meta_train_clean.csv')\n\n# Calculate slice ratio (to generalise better)\nslice_max_train = meta_train.groupby('StudyInstanceUID')['Slice'].max().to_dict()\nmeta_train['SliceRatio'] = 0\nmeta_train['SliceRatio'] = meta_train['Slice']/meta_train['StudyInstanceUID'].map(slice_max_train)\n\n# Initialise targets\nmeta_train[targets]=0\n\n# Predict targets for entire train set\nmeta_train[targets] = clf.predict(meta_train[features])\n\n# We know images with segmentations have 100% accurate targets so put these back in\nmeta_train.loc[meta_train['StudyInstanceUID'].isin(meta_seg['StudyInstanceUID']),targets] = meta_seg[targets].values\n\n# Save to csv\nmeta_train.to_csv('meta_train_with_vertebrae.csv', index=False)\n\n# Preview\nmeta_train.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-11-28T11:30:49.069257Z","iopub.execute_input":"2022-11-28T11:30:49.069829Z","iopub.status.idle":"2022-11-28T11:31:47.433797Z","shell.execute_reply.started":"2022-11-28T11:30:49.069781Z","shell.execute_reply":"2022-11-28T11:31:47.432583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(20,16))\nfor i, Cx in enumerate(targets):\n    plt.subplot(4,2,i+1)\n    sns.histplot(meta_train.groupby('StudyInstanceUID')[Cx].sum())\n    plt.title(f'Number of slices: {Cx}')\nfig.tight_layout()","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2022-11-28T11:31:47.435382Z","iopub.execute_input":"2022-11-28T11:31:47.436146Z","iopub.status.idle":"2022-11-28T11:31:50.32852Z","shell.execute_reply.started":"2022-11-28T11:31:47.436101Z","shell.execute_reply":"2022-11-28T11:31:50.327167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pickle","metadata":{"execution":{"iopub.status.busy":"2022-11-28T11:36:19.1087Z","iopub.execute_input":"2022-11-28T11:36:19.109297Z","iopub.status.idle":"2022-11-28T11:36:19.117839Z","shell.execute_reply.started":"2022-11-28T11:36:19.109249Z","shell.execute_reply":"2022-11-28T11:36:19.11642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filename = 'randomforest_model.sav'\npickle.dump(clf, open(filename, 'wb'))","metadata":{"execution":{"iopub.status.busy":"2022-11-28T11:37:09.000467Z","iopub.execute_input":"2022-11-28T11:37:09.001811Z","iopub.status.idle":"2022-11-28T11:37:09.128057Z","shell.execute_reply.started":"2022-11-28T11:37:09.001769Z","shell.execute_reply":"2022-11-28T11:37:09.127024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}