{"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":"none","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"}],"dockerImageVersionId":30715,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport time\nimport matplotlib.pyplot as plt\nimport plotly.express as px\nimport seaborn as sns\nimport pydicom as dicom\nimport pydicom\nimport json\nimport glob\nimport collections\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport cv2\nfrom skimage import measure\nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\nimport plotly.graph_objects as go\nimport random\nfrom glob import glob\nimport warnings\nwarnings.filterwarnings('ignore')\n# %matplotlib notebook","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-21T19:20:21.627895Z","iopub.execute_input":"2024-06-21T19:20:21.628309Z","iopub.status.idle":"2024-06-21T19:20:21.637041Z","shell.execute_reply.started":"2024-06-21T19:20:21.628278Z","shell.execute_reply":"2024-06-21T19:20:21.635495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read data\ntrain_path = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/'\n\ntrain  = pd.read_csv(train_path + 'train.csv')\nlabel = pd.read_csv(train_path + 'train_label_coordinates.csv')\ntrain_desc  = pd.read_csv(train_path + 'train_series_descriptions.csv')\ntest_desc   = pd.read_csv(train_path + 'test_series_descriptions.csv')\nsub         = pd.read_csv(train_path + 'sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.639626Z","iopub.execute_input":"2024-06-21T19:20:21.640236Z","iopub.status.idle":"2024-06-21T19:20:21.762568Z","shell.execute_reply.started":"2024-06-21T19:20:21.640181Z","shell.execute_reply":"2024-06-21T19:20:21.760851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.764819Z","iopub.execute_input":"2024-06-21T19:20:21.765388Z","iopub.status.idle":"2024-06-21T19:20:21.795329Z","shell.execute_reply.started":"2024-06-21T19:20:21.765342Z","shell.execute_reply":"2024-06-21T19:20:21.793837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.797506Z","iopub.execute_input":"2024-06-21T19:20:21.798028Z","iopub.status.idle":"2024-06-21T19:20:21.819962Z","shell.execute_reply.started":"2024-06-21T19:20:21.797990Z","shell.execute_reply":"2024-06-21T19:20:21.818274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_desc.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.823636Z","iopub.execute_input":"2024-06-21T19:20:21.824636Z","iopub.status.idle":"2024-06-21T19:20:21.839997Z","shell.execute_reply.started":"2024-06-21T19:20:21.824593Z","shell.execute_reply":"2024-06-21T19:20:21.838821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_desc.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.841917Z","iopub.execute_input":"2024-06-21T19:20:21.842443Z","iopub.status.idle":"2024-06-21T19:20:21.859152Z","shell.execute_reply.started":"2024-06-21T19:20:21.842396Z","shell.execute_reply":"2024-06-21T19:20:21.857597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.860976Z","iopub.execute_input":"2024-06-21T19:20:21.861555Z","iopub.status.idle":"2024-06-21T19:20:21.880304Z","shell.execute_reply.started":"2024-06-21T19:20:21.861506Z","shell.execute_reply":"2024-06-21T19:20:21.879044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_desc.loc[train_desc['study_id']==100206310]","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.881761Z","iopub.execute_input":"2024-06-21T19:20:21.882129Z","iopub.status.idle":"2024-06-21T19:20:21.902028Z","shell.execute_reply.started":"2024-06-21T19:20:21.882098Z","shell.execute_reply":"2024-06-21T19:20:21.900533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.loc[(train['study_id']==100206310)]","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.904039Z","iopub.execute_input":"2024-06-21T19:20:21.904486Z","iopub.status.idle":"2024-06-21T19:20:21.934862Z","shell.execute_reply.started":"2024-06-21T19:20:21.904445Z","shell.execute_reply":"2024-06-21T19:20:21.933465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label.loc[(label['study_id']==100206310) & (label['series_id']==1012284084)]","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:21.952318Z","iopub.execute_input":"2024-06-21T19:20:21.952682Z","iopub.status.idle":"2024-06-21T19:20:21.976814Z","shell.execute_reply.started":"2024-06-21T19:20:21.952641Z","shell.execute_reply":"2024-06-21T19:20:21.975401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_path = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images\"\nstudy = \"100206310\"\nseries = \"1012284084\"\ninstance = \"20.dcm\"\npath = study + '/' + series + '/' + instance\nl = label.loc[(label['study_id']==int(study)) & (label['series_id']==int(series)) & (label['instance_number']==int(instance[:-4]))]\n# l = label.loc[(label['study_id']==int(study)) & (label['series_id']==int(series))]\n\nds = dicom.dcmread(os.path.join(base_path, path))\nplt.gca().imshow(ds.pixel_array)\nfor p in range(len(l)):\n    x = l['x'].iloc[p]\n    y = l['y'].iloc[p]\n    circle = plt.Circle([x,y], 5, fill = False, color='r' )\n    plt.gca().add_patch(circle)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:28:25.530182Z","iopub.execute_input":"2024-06-21T19:28:25.530628Z","iopub.status.idle":"2024-06-21T19:28:25.931341Z","shell.execute_reply.started":"2024-06-21T19:28:25.530597Z","shell.execute_reply":"2024-06-21T19:28:25.929870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper functions","metadata":{}},{"cell_type":"code","source":"def split_condition(condition):\n    x = [word[0].upper()+word[1:] for word in condition.split('_')]\n    condition = \"\"\n    for i in x[:-2]:\n        condition += i\n        condition += \" \"\n    level = x[-2] + \"/\" + x[-1]\n    return condition[:-1], level","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:22.385279Z","iopub.execute_input":"2024-06-21T19:20:22.385698Z","iopub.status.idle":"2024-06-21T19:20:22.394703Z","shell.execute_reply.started":"2024-06-21T19:20:22.385662Z","shell.execute_reply":"2024-06-21T19:20:22.393141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\nfrom matplotlib import animation, rc\nfrom IPython.display import HTML\n\nrc('animation', html='jshtml')\n\ndef load_dicom(filename):\n    ds = pydicom.dcmread(filename)\n    return ds.pixel_array\n\ndef load_dicom_line(path, instance_path):\n    t_paths = sorted(\n        glob.glob(os.path.join(path, \"*\")), \n        key=lambda x: int(os.path.splitext(os.path.basename(x))[0].split(\"-\")[-1]),\n    )\n    images = []\n    first = []\n    for filename in t_paths:\n#         print(filename)\n        data = load_dicom(filename)\n        if data.max() == 0:\n            continue\n        images.append(data)\n        \n        if filename == instance_path:\n            first.append(data)\n        \n    return first+images\n\ndef create_animation(images, ax, patches, texts):\n    imgs = []\n    for i in range(len(images)):\n        circle = plt.Circle(patches[i], 20, fill = False, color='r' )\n        ax[i].add_patch(circle)\n        ax[i].title.set_text(texts[i])\n        im = ax[i].imshow(images[i][0])\n        imgs.append(im)\n\n    def animate_func(f):\n        for i in range(len(images)):\n            if(f<len(images[i])):\n                imgs[i].set_array(images[i][f])\n            else:\n                imgs[i].set_array(images[i][0])\n        return imgs\n\n    return animation.FuncAnimation(fig, animate_func, frames=max(len(images[0]),len(images[1]), len(images[2])), interval=1000//24)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:20:22.399349Z","iopub.execute_input":"2024-06-21T19:20:22.399865Z","iopub.status.idle":"2024-06-21T19:20:22.421435Z","shell.execute_reply.started":"2024-06-21T19:20:22.399829Z","shell.execute_reply":"2024-06-21T19:20:22.419708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize single Condition","metadata":{}},{"cell_type":"code","source":"pd.DataFrame(train.columns.tolist())","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:37:52.112157Z","iopub.execute_input":"2024-06-21T19:37:52.112708Z","iopub.status.idle":"2024-06-21T19:37:52.129079Z","shell.execute_reply.started":"2024-06-21T19:37:52.112664Z","shell.execute_reply":"2024-06-21T19:37:52.127635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nHere, one can change the 'condition_idx' parameter to visualize different condition","metadata":{}},{"cell_type":"code","source":"folder_path = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images'\npathologies = list(train)[1:]\nstage = ['Normal/Mild', 'Moderate', 'Severe']\n\"\"\"\n    condition_idx : define the index of condition\n    patient_idx : define the index of patient\n\"\"\"\ncondition_idx = 1\npatient_idx = 0\n","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:46:36.693171Z","iopub.execute_input":"2024-06-21T19:46:36.693587Z","iopub.status.idle":"2024-06-21T19:46:36.703404Z","shell.execute_reply.started":"2024-06-21T19:46:36.693558Z","shell.execute_reply":"2024-06-21T19:46:36.701971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conditions = pathologies[condition_idx]\nfig, ax = plt.subplots(1,3, figsize=(15,5))\nimages = []\npatches = []\ntexts = []\ninstance_nums = []\nfor s in stage:\n    patient = train.loc[train[conditions] == s]\n    condition, level = split_condition(conditions)\n\n    instances = label.loc[(label['study_id'] == list(patient.study_id)[patient_idx]) \n                             & (label['condition'] == condition) \n                             & (label['level'] == level) ]\n\n    for index, row in instances.iterrows():\n        study_id = str(row['study_id'])\n        series_id = str(row['series_id'])\n        instance_number = str(row['instance_number']) + '.dcm'\n        x = row['x']\n        y = row['y']\n\n\n    instance_path = os.path.join(folder_path, study_id, series_id, instance_number)\n    print('Stage:', s, ' path: ', instance_path)\n    dcm_path = os.path.join(folder_path, study_id, series_id)\n    images.append(load_dicom_line(dcm_path, instance_path))\n    patches.append([x,y])\n    texts.append(s)\nfig.suptitle(conditions, fontsize=25)\nanim = create_animation(images, ax, patches, texts)\nHTML(anim.to_jshtml())\n","metadata":{"execution":{"iopub.status.busy":"2024-06-21T19:46:39.801245Z","iopub.execute_input":"2024-06-21T19:46:39.801838Z","iopub.status.idle":"2024-06-21T19:46:56.353222Z","shell.execute_reply.started":"2024-06-21T19:46:39.801787Z","shell.execute_reply":"2024-06-21T19:46:56.351948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# All Lumber Spine Conditions","metadata":{}},{"cell_type":"code","source":"folder_path = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images'\npathologies = list(train)[1:]\nstage = ['Normal/Mild', 'Moderate', 'Severe']\nfor p in pathologies:\n    i = 0\n    fig, ax = plt.subplots(1,3, figsize=(15,5))\n    for s in stage:\n        patient = train.loc[train[p] == s]\n        condition, level = split_condition(p)\n    \n        instances = label.loc[(label['study_id'] == list(patient.study_id)[0]) \n                                 & (label['condition'] == condition) \n                                 & (label['level'] == level) ]\n\n        for index, row in instances.iterrows():\n            study_id = str(row['study_id'])\n            series_id = str(row['series_id'])\n            instance_number = str(row['instance_number']) + '.dcm'\n            x = row['x']\n            y = row['y']\n            \n        \n        instance_path = os.path.join(folder_path, study_id, series_id, instance_number)\n\n        print(instance_path)\n        # load image\n        ds = dicom.dcmread(instance_path)\n        ax[i].imshow(ds.pixel_array)\n        circle = plt.Circle((x, y), 20, fill = False, color='r' )\n        ax[i].add_patch(circle)\n        ax[i].title.set_text(s)\n        i += 1\n    fig.suptitle(p, fontsize=30)\n    plt.show()","metadata":{"execution":{"iopub.status.idle":"2024-06-21T19:21:06.010282Z","shell.execute_reply.started":"2024-06-21T19:20:38.209952Z","shell.execute_reply":"2024-06-21T19:21:06.008933Z"},"trusted":true},"execution_count":null,"outputs":[]}]}