{"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":"markdown","source":"# RNSA 2023 EDA","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:30.341638Z","iopub.execute_input":"2023-08-27T14:30:30.342136Z","iopub.status.idle":"2023-08-27T14:30:31.522023Z","shell.execute_reply.started":"2023-08-27T14:30:30.342095Z","shell.execute_reply":"2023-08-27T14:30:31.520526Z"}}},{"cell_type":"markdown","source":"## Imports","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport plotly.express as px\nimport matplotlib.pyplot as plt\nimport glob\nimport os\nimport pydicom\nfrom tqdm import tqdm\nimport time\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\nfrom plotly.offline import init_notebook_mode, iplot","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:09:45.969685Z","iopub.execute_input":"2023-08-27T20:09:45.970387Z","iopub.status.idle":"2023-08-27T20:09:45.976225Z","shell.execute_reply.started":"2023-08-27T20:09:45.97035Z","shell.execute_reply":"2023-08-27T20:09:45.975273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Folders list","metadata":{}},{"cell_type":"code","source":"main_folder = \"/kaggle/input/rsna-2023-abdominal-trauma-detection/\"\n!ls {main_folder}","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:09:46.776847Z","iopub.execute_input":"2023-08-27T20:09:46.777804Z","iopub.status.idle":"2023-08-27T20:09:48.061515Z","shell.execute_reply.started":"2023-08-27T20:09:46.777766Z","shell.execute_reply":"2023-08-27T20:09:48.059655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's study the files **one by one**. ","metadata":{}},{"cell_type":"markdown","source":"## - train.csv file","metadata":{"execution":{"iopub.status.busy":"2023-08-20T15:30:10.030417Z","iopub.execute_input":"2023-08-20T15:30:10.031306Z","iopub.status.idle":"2023-08-20T15:30:10.037173Z","shell.execute_reply.started":"2023-08-20T15:30:10.031257Z","shell.execute_reply":"2023-08-20T15:30:10.035774Z"}}},{"cell_type":"markdown","source":"**train.csv** Target labels for the train set. Note that patients labeled healthy may still have other medical issues, such as cancer or broken bones, that don't happen to be covered by the competition labels.\n* `patient_id` - A unique ID code for each patient.\n* `[bowel/extravasation]_[healthy/injury]` - The two injury types with binary targets.\n* `[kidney/liver/spleen]_[healthy/low/high` - The three injury types with three target levels.\n* `any_injur` - Whether the patient had any injury at all.\n","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(main_folder + \"train.csv\")\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:12:05.583609Z","iopub.execute_input":"2023-08-27T20:12:05.584871Z","iopub.status.idle":"2023-08-27T20:12:05.615066Z","shell.execute_reply.started":"2023-08-27T20:12:05.58482Z","shell.execute_reply":"2023-08-27T20:12:05.613408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that we have **3147** different patients and one hot encodings as labels. First let's see the correlation matrix between the injuries.","metadata":{}},{"cell_type":"code","source":"from scipy.stats import pointbiserialr\nimport seaborn as sns\n\ninjury_columns = train.columns[1:-1]\n\ncorrelation_matrix = pd.DataFrame(index=injury_columns, columns=injury_columns)\n\nfor col1 in injury_columns:\n    for col2 in injury_columns:\n        # Convert categorical values to numeric using Point Biserial Correlation\n        r, _ = pointbiserialr(train[col1], train[col2])\n        correlation_matrix.loc[col1, col2] = r\n\nmask = np.triu(np.ones(correlation_matrix.shape), k=1)\n\nplt.figure(figsize=(10, 8))\nsns.heatmap(correlation_matrix.astype(float), annot=True, cmap='coolwarm', center=0, mask=mask)\nplt.title('Correlation Heatmap of Injury Columns (Lower Triangle)')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:16:36.267617Z","iopub.execute_input":"2023-08-27T20:16:36.26889Z","iopub.status.idle":"2023-08-27T20:16:37.128673Z","shell.execute_reply.started":"2023-08-27T20:16:36.26883Z","shell.execute_reply":"2023-08-27T20:16:37.127215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now let's see how the injuries are distributed among the patients. But first let's modify the shape of the dataframe.","metadata":{}},{"cell_type":"code","source":"train['bowel'] = train.iloc[:, 1:3].idxmax(1)\ntrain['extravasation'] = train.iloc[:, 3:5].idxmax(1)\ntrain['kidney'] = train.iloc[:, 5:8].idxmax(1)\ntrain['liver'] = train.iloc[:, 8:11].idxmax(1)\ntrain['spleen'] = train.iloc[:, 11:14].idxmax(1)\n\ntrain = train.drop(columns =['bowel_healthy','bowel_injury','extravasation_healthy','extravasation_injury','kidney_healthy','kidney_low','kidney_high','liver_healthy','liver_low','liver_high',\n                             'spleen_healthy','spleen_low','spleen_high'])\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:32.713697Z","iopub.execute_input":"2023-08-27T14:30:32.714218Z","iopub.status.idle":"2023-08-27T14:30:32.855794Z","shell.execute_reply.started":"2023-08-27T14:30:32.714157Z","shell.execute_reply":"2023-08-27T14:30:32.854256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's replace bowel_healthy with 0, bowel_injury with 1, same for extravasation and 0 to 2 for healthy-low-high.","metadata":{}},{"cell_type":"code","source":"train['bowel'] = train['bowel'].replace(['bowel_injury','bowel_healthy'], [1, 0])\ntrain['extravasation'] = train['extravasation'].replace(['extravasation_injury', 'extravasation_healthy'], [0, 1])\ntrain['kidney'] = train['kidney'].replace(['kidney_low','kidney_high','kidney_healthy'], [1, 2, 0])\ntrain['liver'] = train['liver'].replace(['liver_low','liver_high','liver_healthy'], [1, 2, 0])\ntrain['spleen'] = train['spleen'].replace(['spleen_low','spleen_high','spleen_healthy'], [1, 2, 0])\n\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:32.85745Z","iopub.execute_input":"2023-08-27T14:30:32.857809Z","iopub.status.idle":"2023-08-27T14:30:32.896748Z","shell.execute_reply.started":"2023-08-27T14:30:32.857778Z","shell.execute_reply":"2023-08-27T14:30:32.895285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, axes = plt.subplots(2, 3, figsize=(15, 10))\naxes = axes.flatten()\nfor idx, column in enumerate(train.columns[1:]):\n    axes[idx].set_axis_off()\n    ax = axes[idx]\n    possible_values = train[column].nunique()\n    if possible_values == 2:\n        labels = ['Healthy', 'Injured']\n        color_discrete_sequence = ['g','r']\n        sizes = train[column].value_counts().to_dict()\n    else:\n        labels = ['Healthy', 'Low', 'High']\n        color_discrete_sequence = ['g', 'orange', 'r']\n        sizes = train[column].value_counts().to_dict()\n    ax.pie(sizes.values(), labels=labels, colors=color_discrete_sequence)\n    ax.set_title(column)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:32.898377Z","iopub.execute_input":"2023-08-27T14:30:32.89878Z","iopub.status.idle":"2023-08-27T14:30:33.696147Z","shell.execute_reply.started":"2023-08-27T14:30:32.898741Z","shell.execute_reply":"2023-08-27T14:30:33.694601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## - sample_submission.csv","metadata":{}},{"cell_type":"code","source":"sample_submission = pd.read_csv(main_folder + \"sample_submission.csv\")\nsample_submission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:33.698134Z","iopub.execute_input":"2023-08-27T14:30:33.699025Z","iopub.status.idle":"2023-08-27T14:30:33.730396Z","shell.execute_reply.started":"2023-08-27T14:30:33.698974Z","shell.execute_reply":"2023-08-27T14:30:33.729121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We only have to make predictions on **3 patients**.","metadata":{}},{"cell_type":"markdown","source":"## - train_series_meta.csv / test_series_meta.csv","metadata":{}},{"cell_type":"markdown","source":"### train","metadata":{}},{"cell_type":"code","source":"train_series_meta = pd.read_csv(main_folder + \"train_series_meta.csv\")\ntrain_series_meta.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:00:22.763442Z","iopub.execute_input":"2023-08-27T20:00:22.764252Z","iopub.status.idle":"2023-08-27T20:00:22.801735Z","shell.execute_reply.started":"2023-08-27T20:00:22.764164Z","shell.execute_reply":"2023-08-27T20:00:22.800394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sizes = train_series_meta['incomplete_organ'].value_counts().to_dict()\ncolor_discrete_sequence = ['g','r']\nlabels = ['No incomplete organ', '1 incomplete organ']\nfig, ax = plt.pie(sizes.values(), labels=labels, colors=color_discrete_sequence)","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:00:25.323503Z","iopub.execute_input":"2023-08-27T20:00:25.324509Z","iopub.status.idle":"2023-08-27T20:00:25.493533Z","shell.execute_reply.started":"2023-08-27T20:00:25.324464Z","shell.execute_reply":"2023-08-27T20:00:25.491095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A incomplete organ means that it's **croped** on the image.","metadata":{}},{"cell_type":"code","source":"print(\"Number of Unique Values:\\n\",train_series_meta.nunique())","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:00:28.475851Z","iopub.execute_input":"2023-08-27T20:00:28.476356Z","iopub.status.idle":"2023-08-27T20:00:28.487534Z","shell.execute_reply.started":"2023-08-27T20:00:28.476318Z","shell.execute_reply":"2023-08-27T20:00:28.486075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"id_counts = train_series_meta['patient_id'].value_counts()\n\n# Filter out IDs that are duplicated less than two times\nfiltered_id_counts = id_counts[id_counts >= 2]\n\nprint(\"Number of patients that have two series :\", len(filtered_id_counts))\n","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:00:30.102964Z","iopub.execute_input":"2023-08-27T20:00:30.103438Z","iopub.status.idle":"2023-08-27T20:00:30.113426Z","shell.execute_reply.started":"2023-08-27T20:00:30.103402Z","shell.execute_reply":"2023-08-27T20:00:30.112286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now let's check if there's a link between injury and and value of the **aortic** measure. If there is a negative value in the dataset, we take its positive value.","metadata":{}},{"cell_type":"code","source":"c = train_series_meta['aortic_hu']\n\ntrain_series_meta['aortic_hu'] = c.apply(lambda x: abs(x))\n\ncolumn_to_plot = train_series_meta['aortic_hu']\nplt.hist(column_to_plot, bins=10, edgecolor='black')\nplt.xlabel('Values')\nplt.ylabel('Frequency')\nplt.title('Histogram of Values')\n\n\nmerged_df = train_series_meta.merge(train[['patient_id', 'any_injury']], on='patient_id', how='left')\n\nnum_datasets = 50\n\nmin_aortic = merged_df['aortic_hu'].min()\nmax_aortic = merged_df['aortic_hu'].max()\nbins = [min_aortic + i * (max_aortic - min_aortic) / num_datasets for i in range(num_datasets + 1)]\n\nmerged_df['dataset'] = pd.cut(merged_df['aortic_hu'], bins=bins, labels=range(1, num_datasets + 1))\n\ndatasets = {}\nfor i in range(1, num_datasets + 1):\n    datasets[i] = merged_df[merged_df['dataset'] == i].drop(columns=['dataset'])\n\nheights_injury = [dataset['any_injury'].sum() / max(1,dataset.shape[0]) for dataset in datasets.values()]\n\nbin_widths = [bins[i+1] - bins[i] for i in range(len(bins)-1)]\n\nfig, ax = plt.subplots(figsize=(10, 6))\n\nfor i, (bin_val, height) in enumerate(zip(bins[:-1], heights_injury)):\n    ax.bar(bin_val, height, width=bin_widths[i], color='red')\n    ax.bar(bin_val, 1 - height, bottom=height, width=bin_widths[i], color='green')\n\nax.set_xlabel('Bins')\nax.set_ylabel('Proportion')\nax.set_title('Proportion of injured for different ranges')\n\n# Show the plot\nplt.show()\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2023-08-27T20:02:25.187534Z","iopub.execute_input":"2023-08-27T20:02:25.188696Z","iopub.status.idle":"2023-08-27T20:02:26.478287Z","shell.execute_reply.started":"2023-08-27T20:02:25.188653Z","shell.execute_reply":"2023-08-27T20:02:26.476766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that all the aortic_hu value is quite independant from the health of the patients.","metadata":{}},{"cell_type":"markdown","source":"### test","metadata":{}},{"cell_type":"code","source":"test_series_meta = pd.read_csv(main_folder + \"test_series_meta.csv\")\ntest_series_meta.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:33.976599Z","iopub.execute_input":"2023-08-27T14:30:33.977481Z","iopub.status.idle":"2023-08-27T14:30:34.004176Z","shell.execute_reply.started":"2023-08-27T14:30:33.977435Z","shell.execute_reply":"2023-08-27T14:30:34.003017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Number of Unique Values:\\n\",test_series_meta.nunique())","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:34.00585Z","iopub.execute_input":"2023-08-27T14:30:34.006576Z","iopub.status.idle":"2023-08-27T14:30:34.016285Z","shell.execute_reply.started":"2023-08-27T14:30:34.006535Z","shell.execute_reply":"2023-08-27T14:30:34.014949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In the test_images folder, we only have 3 of the 6 series (which means half the series are useless).","metadata":{}},{"cell_type":"markdown","source":"## - image_level_labels.csv","metadata":{}},{"cell_type":"code","source":"image_level_labels = pd.read_csv(main_folder + \"image_level_labels.csv\")\nimage_level_labels.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:34.018385Z","iopub.execute_input":"2023-08-27T14:30:34.019286Z","iopub.status.idle":"2023-08-27T14:30:34.055701Z","shell.execute_reply.started":"2023-08-27T14:30:34.019242Z","shell.execute_reply":"2023-08-27T14:30:34.054257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Types of injuries: \", image_level_labels['injury_name'].unique())\nprint(\"Number of patients: \", image_level_labels['patient_id'].nunique())\nprint(\"Number of series_id: \", image_level_labels['series_id'].nunique())","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:34.057505Z","iopub.execute_input":"2023-08-27T14:30:34.058537Z","iopub.status.idle":"2023-08-27T14:30:34.072393Z","shell.execute_reply.started":"2023-08-27T14:30:34.058487Z","shell.execute_reply":"2023-08-27T14:30:34.071137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that every image of very serie is annotated. Let's study this data further.","metadata":{}},{"cell_type":"code","source":"print(\"Number of rows = number of annotations \", image_level_labels.shape[0])","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:34.073717Z","iopub.execute_input":"2023-08-27T14:30:34.075313Z","iopub.status.idle":"2023-08-27T14:30:34.087808Z","shell.execute_reply.started":"2023-08-27T14:30:34.075265Z","shell.execute_reply":"2023-08-27T14:30:34.086169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This means that we have **12 029 annotations**.","metadata":{}},{"cell_type":"code","source":"data = image_level_labels.groupby('series_id')['instance_number'].nunique()\nprint(sum(data))\nplt.hist(data, bins=len(data), edgecolor='black')  \nplt.xlabel('Number of images per serie')\nplt.ylabel('Frequence')\nplt.title('Frequence VS number of images per serie')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:34.089814Z","iopub.execute_input":"2023-08-27T14:30:34.090904Z","iopub.status.idle":"2023-08-27T14:30:34.96071Z","shell.execute_reply.started":"2023-08-27T14:30:34.090863Z","shell.execute_reply":"2023-08-27T14:30:34.958275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are **11 536** images and **12 029** annotations. This means that on some images, there is **both injuries**. We can see on the graph that most series have around 20-30 instance_number, that is 20-30 images of the CT scan (that have around 1000 images in general) where the injury is visible. Let's visualize that.","metadata":{}},{"cell_type":"code","source":"image_level_labels['injury_name'] = image_level_labels['injury_name'].replace(['Active_Extravasation', 'Bowel'], [1,2])\n\nseries_id = list(image_level_labels['series_id'].unique())\n\nmax_instances = max(image_level_labels.groupby('series_id')['instance_number'].max())\n\nresult_list = [[0] * max_instances for _ in range(image_level_labels['series_id'].nunique())]\n\nfor i, row in image_level_labels.iterrows():\n    if result_list[series_id.index(row['series_id'])][row['instance_number'] - 1] != 0:\n        result_list[series_id.index(row['series_id'])][row['instance_number'] - 1] = 3\n    else:\n        result_list[series_id.index(row['series_id'])][row['instance_number'] - 1] = row['injury_name']\n\ncolor_mapping = {0: 'g', 1: 'r', 2: 'b', 3: 'm'}\nlegend_mapping = {0: 'no injury', 1: 'active extravasation', 2: 'bowel', 3: 'both injuries'}\n\nplt.figure(figsize=(10, 90))\n\nfor i, sublist in enumerate(result_list):\n    x_values = np.arange(len(sublist))\n    y_values = np.full(len(sublist),i)\n    colors = [color_mapping[val] for val in sublist]\n    plt.scatter(x_values, y_values, color=colors)\n\nplt.yticks(range(len(result_list)), [f'Série {i+1}' for i in range(len(result_list))])\nplt.xlabel('Images')\nplt.ylabel('Série')\nplt.title('CT scans active extravasation/bowel injury vizualisation')\nplt.legend([plt.Line2D([0], [0], marker='o', color='w', label=legend_mapping[val], markersize=10, markerfacecolor=color_mapping[val]) for val in color_mapping], legend_mapping.values())\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:34.962465Z","iopub.execute_input":"2023-08-27T14:30:34.962859Z","iopub.status.idle":"2023-08-27T14:30:59.766397Z","shell.execute_reply.started":"2023-08-27T14:30:34.962826Z","shell.execute_reply":"2023-08-27T14:30:59.764639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To sum up, we have **330 series** of **246 patients** that are annotated image by image for the extravasation and bowel. The reason for those special annotations is that unlike kidney, liver or spleen, these injuries are not local and can happen everywhere on the CT scan so they need to be located.","metadata":{}},{"cell_type":"markdown","source":"## - train_dicom_tags.parquet","metadata":{}},{"cell_type":"code","source":"train_dicom_tags = pd.read_parquet(main_folder + \"train_dicom_tags.parquet\")\ntrain_dicom_tags.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:30:59.768456Z","iopub.execute_input":"2023-08-27T14:30:59.768937Z","iopub.status.idle":"2023-08-27T14:31:07.695607Z","shell.execute_reply.started":"2023-08-27T14:30:59.768895Z","shell.execute_reply":"2023-08-27T14:31:07.694469Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Number of rows: \", train_dicom_tags.shape[0])\nprint(\"Number of images: \", train_dicom_tags['path'].nunique())","metadata":{"execution":{"iopub.status.busy":"2023-08-27T14:31:07.697082Z","iopub.execute_input":"2023-08-27T14:31:07.698007Z","iopub.status.idle":"2023-08-27T14:31:08.487418Z","shell.execute_reply.started":"2023-08-27T14:31:07.69793Z","shell.execute_reply":"2023-08-27T14:31:08.485376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In total we have **1 510 373 images**.","metadata":{}},{"cell_type":"markdown","source":"# Visualize DICOM files for a scan ","metadata":{}},{"cell_type":"code","source":"FILEPATH = '/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10004/21057/1000.dcm'","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:35:37.564261Z","iopub.execute_input":"2023-08-27T18:35:37.564795Z","iopub.status.idle":"2023-08-27T18:35:37.571918Z","shell.execute_reply.started":"2023-08-27T18:35:37.564736Z","shell.execute_reply":"2023-08-27T18:35:37.570549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = pydicom.dcmread(FILEPATH)","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:35:37.573142Z","iopub.execute_input":"2023-08-27T18:35:37.573585Z","iopub.status.idle":"2023-08-27T18:35:37.587988Z","shell.execute_reply.started":"2023-08-27T18:35:37.573549Z","shell.execute_reply":"2023-08-27T18:35:37.586601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def select_evenly_spaced_elements(input_list, k):\n    n = len(input_list)\n    step = n / k\n    selected_indices = [int(i * step) for i in range(k)]\n    selected_elements = [input_list[i] for i in selected_indices]\n    return np.array(selected_elements)\n\ndef create_3D_scans(folder, downsample_rate=1): \n    filenames = os.listdir(folder)\n    filenames = [int(filename.split('.')[0]) for filename in filenames]\n    filenames = sorted(filenames)\n    filenames = [str(filename) + '.dcm' for filename in filenames]\n        \n    volume = []\n    for filename in tqdm(filenames[::4]):\n        filepath = os.path.join(folder, filename)\n        ds = pydicom.dcmread(filepath)\n        image = ds.pixel_array\n        \n        # find rescale params\n        if (\"RescaleIntercept\" in ds) and (\"RescaleSlope\" in ds):\n            intercept = float(ds.RescaleIntercept)\n            slope = float(ds.RescaleSlope)\n    \n        # find clipping params\n        center = int(ds.WindowCenter)\n        width = int(ds.WindowWidth)\n        low = center - width / 2\n        high = center + width / 2    \n        \n        \n        image = (image * slope) + intercept\n        image = np.clip(image, low, high)\n\n        image = (image / np.max(image) * 255).astype(np.int16)\n        image = image[::downsample_rate, ::downsample_rate]\n        volume.append( image )\n    \n    volume = np.stack(volume, axis=0)\n    volumes = {\"axial\": volume,\n               \"coronal\": volume.transpose([1, 0, 2]),\n               \"sagittal\": volume.transpose([2, 0, 1])}\n    reverse_coronal = volumes['coronal'][::-1]\n    volumes['coronal'] = reverse_coronal\n    reverse_sagittal = np.flip(volumes['sagittal'], axis=2)\n    volumes['sagittal'] = reverse_sagittal\n    \n    select_axial = select_evenly_spaced_elements(volumes['axial'], volumes['coronal'].shape[0])\n    reverse_axial = select_axial[::-1]\n    volumes['coronal'] = reverse_axial   \n    return volumes\n","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:37:15.865243Z","iopub.execute_input":"2023-08-27T18:37:15.865708Z","iopub.status.idle":"2023-08-27T18:37:15.88293Z","shell.execute_reply.started":"2023-08-27T18:37:15.865674Z","shell.execute_reply":"2023-08-27T18:37:15.881787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PATH = '/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10004/21057/'\nvolumes = create_3D_scans(PATH, 8)","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:37:16.271047Z","iopub.execute_input":"2023-08-27T18:37:16.272317Z","iopub.status.idle":"2023-08-27T18:37:21.239427Z","shell.execute_reply.started":"2023-08-27T18:37:16.272271Z","shell.execute_reply":"2023-08-27T18:37:21.23623Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(volumes['sagittal'].shape)\nprint(volumes['axial'].shape)\nprint(volumes['coronal'].shape)","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:37:21.241654Z","iopub.execute_input":"2023-08-27T18:37:21.242048Z","iopub.status.idle":"2023-08-27T18:37:21.249379Z","shell.execute_reply.started":"2023-08-27T18:37:21.242014Z","shell.execute_reply":"2023-08-27T18:37:21.247635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"axial_w = volumes['axial'].shape[1]\naxial_h = volumes['axial'].shape[2]\ncoronal_w = volumes['coronal'].shape[2]\ncoronal_h = volumes['coronal'].shape[1]\nsagittal_w = volumes['sagittal'].shape[2]\nsagittal_h = volumes['sagittal'].shape[1]","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:37:26.347121Z","iopub.execute_input":"2023-08-27T18:37:26.347588Z","iopub.status.idle":"2023-08-27T18:37:26.354049Z","shell.execute_reply.started":"2023-08-27T18:37:26.347553Z","shell.execute_reply":"2023-08-27T18:37:26.352878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"nb_frames = min(volumes['axial'].shape)\n\nfig=make_subplots(rows=1, cols=3, specs=[[{\"type\":\"surface\"},{\"type\":\"surface\"},{\"type\":\"surface\"}]], subplot_titles=(\"Axial\", \"Coronal\", \"Sagittal\"))\n\nfig.add_trace(go.Surface(\n    z=nb_frames * 0.1 * np.ones((axial_w, axial_h)),\n    surfacecolor=np.flipud(volumes['axial'][nb_frames - 1]),\n    ),row=1,col=1)\n\nx_cor,z_cor = np.meshgrid(np.linspace(0,coronal_w,coronal_w), np.linspace(0,coronal_h,coronal_h))\nfig.add_trace(go.Surface(\n    x=x_cor, z=z_cor, y=nb_frames * 0.1 * np.ones((coronal_h, coronal_w)),\n    surfacecolor=np.flipud(volumes['coronal'][1]),\n    ),row=1,col=2)\n\ny_sag,z_sag = np.meshgrid(np.linspace(0,sagittal_w,sagittal_w), np.linspace(0,sagittal_h,sagittal_h))\nfig.add_trace(go.Surface(\n    x=nb_frames * 0.1 * np.ones((sagittal_h, sagittal_w)), z=z_sag, y=y_sag,\n    surfacecolor=np.flipud(volumes['sagittal'][1]),\n    ),row=1,col=3)\n\nframes=[go.Frame(data=[go.Surface(z=(nb_frames * 0.1 - k * 0.1) * np.ones((axial_w, axial_h)),surfacecolor=np.flipud(volumes['axial'][nb_frames - k - 1])),\n                       go.Surface(y=(nb_frames * 0.1 - k * 0.1) * np.ones((coronal_h, coronal_w)),surfacecolor=np.flipud(volumes['coronal'][nb_frames - k - 1])),\n                       go.Surface(x=(nb_frames * 0.1 - k * 0.1) * np.ones((sagittal_h, sagittal_w)),surfacecolor=np.flipud(volumes['sagittal'][nb_frames - k - 1]))],\n                 name=str(k)) for k in range(nb_frames)]  \n\nfig.update(frames=frames)\n\nfig.update_layout(scene1_xaxis=dict(showticklabels=False, showline=False),\n                  scene1_yaxis=dict(showticklabels=False, showline=False),\n                  scene1_zaxis=dict(range=[0, nb_frames * 0.1], showticklabels=False, showline=False, autorange=False),\n                  scene2_xaxis=dict(showticklabels=False, showline=False),\n                  scene2_yaxis=dict(range=[0, nb_frames * 0.1], showticklabels=False, showline=False, autorange=False),\n                  scene2_zaxis=dict(showticklabels=False, showline=False),\n                  scene3_xaxis=dict(range=[0, nb_frames * 0.1], showticklabels=False, showline=False, autorange=False),\n                  scene3_yaxis=dict(showticklabels=False, showline=False),\n                  scene3_zaxis=dict(showticklabels=False, showline=False),)\n        \ndef frame_args(duration):\n    return {\n            \"frame\": {\"duration\": duration},\n            \"mode\": \"immediate\",\n            \"fromcurrent\": True,\n            \"transition\": {\"duration\": duration, \"easing\": \"linear\"},\n        }\n\nfr_duration=50\nsliders = [\n            {\n                \"pad\": {\"b\": 10, \"t\": 50},\n                \"len\": 0.9,\n                \"x\": 0.1,\n                \"y\": 0,\n                \"steps\": [\n                    {\n                       \"args\": [[f.name], frame_args(fr_duration)],\n                        \"label\": f\"fr{k+1}\",\n                        \"method\": \"animate\",\n                    }\n                     for k, f in enumerate(fig.frames)\n                ],\n            }\n        ]\n\n\nfig.update_layout(sliders=sliders,\n                  updatemenus = [\n                        {\n                        \"buttons\": [\n                            {\n                             \"args\": [None, frame_args(fr_duration)],\n                             \"label\": \"&#9654;\", # play symbol\n                             \"method\": \"animate\",\n                            },\n                            {\n                             \"args\": [[None], frame_args(fr_duration)],\n                             \"label\": \"&#9724;\", # pause symbol\n                             \"method\": \"animate\",\n                            }],\n                        \"direction\": \"left\",\n                        \"pad\": {\"r\": 10, \"t\": 70},\n                        \"type\": \"buttons\",\n                        \"x\": 0.1,\n                        \"y\": 0,\n                        }])\n","metadata":{"execution":{"iopub.status.busy":"2023-08-27T18:57:59.827284Z","iopub.execute_input":"2023-08-27T18:57:59.828509Z","iopub.status.idle":"2023-08-27T18:58:01.097013Z","shell.execute_reply.started":"2023-08-27T18:57:59.828449Z","shell.execute_reply":"2023-08-27T18:58:01.09508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The last folder is the segmentations folder, where we have 206 scans where organs are segmented.  ","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}