{"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 # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport matplotlib.patches as patches\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## train\n- study_id - The study ID. Each study may include multiple series of images.\n- [condition]_[level] - The target labels, such as spinal_canal_stenosis_l1_l2, with the severity levels of Normal/Mild, Moderate, or Severe. \nSome entries have incomplete labels.","metadata":{}},{"cell_type":"code","source":"# read train.csv\ntrain_csv = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train.csv\")\ntrain_csv.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv.info()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## NAs count","metadata":{}},{"cell_type":"code","source":"train_csv.columns","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.DataFrame(train_csv.isna().sum()).reset_index().rename({'index': 'columns', 0 : 'NAs count'}, axis=1).sort_values(by='NAs count', ascending=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## How many folders do we have in train_images folder ?","metadata":{}},{"cell_type":"code","source":"train_img_folder_list = os.listdir(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images\")\n\nlen(train_img_folder_list)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It's OK ! it corresponds to the number of rows in train_csv","metadata":{}},{"cell_type":"code","source":"train_csv[[\"study_id\", \"spinal_canal_stenosis_l2_l3\"]].groupby(by=\"study_id\").count()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train labels coordinates\n- study_id\n- series_id - The imagery series ID.\n- instance_number - The image's order number within the 3D stack.\n- condition - There are three core conditions: spinal canal stenosis, neural_foraminal_narrowing, and subarticular_stenosis. The latter two are considered for each side of the spine.\n- level - The relevant vertebrae, such as l3_l4\n- [x/y] - The x/y coordinates for the center of the area that defined the label.","metadata":{}},{"cell_type":"code","source":"train_labels_coord = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_label_coordinates.csv\")\ntrain_labels_coord.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.DataFrame(train_labels_coord.isna().sum()).reset_index().rename({'index': 'columns', 0 : 'NAs count'}, axis=1).sort_values(by='NAs count', ascending=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### For each study_id, how many rows do we have in train labels coordinate ?","metadata":{}},{"cell_type":"code","source":"train_labels_coord[[\"study_id\", \"series_id\"]].groupby(by=\"study_id\").count().sort_values(by=\"series_id\", ascending=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In the train images folder, how many sub-folder do we have for each folder ?","metadata":{}},{"cell_type":"code","source":"train_folders = []\ntrain_sub_folders_count = []\nn_images = []\nfor train_fold in train_img_folder_list:\n    train_folders.append(train_fold)\n    sub_fold_list = os.listdir(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/\" + train_fold)\n    train_sub_folders_count.append(len(sub_fold_list))\n    # number of images in each sub-folder\n    n_temp = 0\n    for sub_fold in sub_fold_list:\n        n_temp += len(os.listdir(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/\" + train_fold + \"/\" + sub_fold))\n    n_images.append(n_temp)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images_structure_df = pd.DataFrame({\"train_folders\" : train_folders, \"train_sub_folders_count\":train_sub_folders_count, \"n_images\":n_images}).sort_values(by=\"n_images\", ascending=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images_structure_df.head(10)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images_structure_df.to_csv(\"/kaggle/working/folder_train_images_structure.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train/test description\n- study_id\n- series_id\n- series_description The scan's orientation.\n","metadata":{}},{"cell_type":"code","source":"train_series_desc = pd.read_csv(\"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_series_descriptions.csv\")\ntrain_series_desc.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's see for study id in train, how many rows we have in label coordinates and series description : ","metadata":{}},{"cell_type":"markdown","source":"# Unique values of each column\n## train_csv","metadata":{}},{"cell_type":"code","source":"for c in train_csv.columns:\n    print(c, \" - number of unique values : \", len(train_csv[c].unique()))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## train labels","metadata":{}},{"cell_type":"code","source":"for c in train_labels_coord.columns:\n    print(c, \" - number of unique values : \", len(train_labels_coord[c].unique()))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## train_series_desc","metadata":{}},{"cell_type":"code","source":"for c in train_series_desc.columns:\n    print(c, \" - number of unique values : \", len(train_series_desc[c].unique()))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_id_list = list(train_csv.study_id.values)\nstudy_id_list[0:10]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's focus on one folder","metadata":{}},{"cell_type":"code","source":"study_id = 1050200728 # 100206310     \nseries_id = 1585900432 #1012284084","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_csv.loc[(train_csv[\"study_id\"]==study_id),:]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_id_df = train_labels_coord.loc[(train_labels_coord[\"study_id\"]==study_id) & (train_labels_coord[\"series_id\"]==series_id),:]\nstudy_id_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_id_df.info()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's see how many images do we have in the corresponding folder","metadata":{}},{"cell_type":"code","source":"path_ = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/\"\npath_ = path_ + str(study_id) + \"/\" + str(series_id) + \"/\"\nimages_list = os.listdir(path_)\nprint(len(images_list))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# series desciption\ntrain_series_desc.loc[(train_series_desc[\"study_id\"]==study_id) & (train_series_desc[\"series_id\"]== series_id),:]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's read the first image","metadata":{}},{"cell_type":"code","source":"import pydicom as dicom\nimport matplotlib.patches as patches\n\n# plots\nimport matplotlib.pyplot as plt\nfrom matplotlib import animation, rc\nimport plotly.express as px\nimport seaborn as sns\nimport plotly.express as px\nimport cv2","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# images_path = \"/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/train_images/\" + str(study_id) + \"/\" + str(series_id) +\"/\"\nds = dicom.dcmread(path_ + images_list[0])\n\nfig, ax = plt.subplots(figsize=(16, 8))\nax.imshow(ds.pixel_array, cmap =plt.cm.bone)     # Display the image\n\n# Add the xs and ys\nfor x,y in zip(study_id_df[\"x\"].values, study_id_df[\"y\"].values):\n    rect = patches.Circle(xy = (x, y), linewidth=2, edgecolor='r', facecolor=\"none\") # (x, y), width, height\n    ax.add_patch(rect)\n# diplay\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}