{"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":"<div class='alert alert-info' style='text-align: center;'><h1>RSNA-MICCAI Brain Tumor Image Planes and Counts</h1></div>\n                                                  \n#### This notebook gets all the image planes and slice counts for each series in the train set and appends them to the labels dataframe.\n\n- The same technique can be applied to the test set to ensure coplanar comparissons.\n- You can run it yourself, or just D/L the output of this notebook and import into your own.\n- Here, we'll get an image from each series and check the plane.","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:40:43.104764Z","iopub.execute_input":"2021-08-31T20:40:43.105124Z","iopub.status.idle":"2021-08-31T20:40:43.110508Z","shell.execute_reply.started":"2021-08-31T20:40:43.105091Z","shell.execute_reply":"2021-08-31T20:40:43.108872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_names = ['FLAIR','T1w','T1wCE','T2w']\ndirectory = '../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/'\nlabels_df = pd.read_csv('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv')","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:40:43.116288Z","iopub.execute_input":"2021-08-31T20:40:43.116791Z","iopub.status.idle":"2021-08-31T20:40:43.132604Z","shell.execute_reply.started":"2021-08-31T20:40:43.116741Z","shell.execute_reply":"2021-08-31T20:40:43.131430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get an image path from a series, we'll return only the tenth image in the series directory\ndef get_series_list(study_id, series_name):\n \n    files = [os.path.join(directory + '' + study_id + \"/\" + series_name, f) for f in os.listdir(directory + '' + study_id + \"/\" + series_name) if \n    os.path.isfile(os.path.join(directory + '' + study_id + \"/\" + series_name, f))]\n    return files[10], len(files)","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:40:43.133901Z","iopub.execute_input":"2021-08-31T20:40:43.134378Z","iopub.status.idle":"2021-08-31T20:40:43.141977Z","shell.execute_reply.started":"2021-08-31T20:40:43.134322Z","shell.execute_reply":"2021-08-31T20:40:43.141186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert the Image Orientation Patient tag cosine values into a text string of the plane.\n# This is a simple method to represent the plane the image is 'closest to' .. it does not explain any obliqueness.\n# There is a more complex (and complete) way to do this, but this is all we need here since all the planes in this dataset are orthogonal.\ndef get_image_plane(loc):\n\n    row_x = round(loc[0])\n    row_y = round(loc[1])\n    row_z = round(loc[2])\n    col_x = round(loc[3])\n    col_y = round(loc[4])\n    col_z = round(loc[5])\n    if (row_x, row_y, col_x, col_y) == (1,0,0,0):\n        return \"Coronal\"\n    if (row_x, row_y, col_x, col_y) == (0,1,0,0):\n        return \"Sagittal\"\n    if (row_x, row_y, col_x, col_y) == (1,0,0,1):\n        return \"Axial\"\n    return \"Unknown\"","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:40:43.143505Z","iopub.execute_input":"2021-08-31T20:40:43.143909Z","iopub.status.idle":"2021-08-31T20:40:43.160611Z","shell.execute_reply.started":"2021-08-31T20:40:43.143867Z","shell.execute_reply":"2021-08-31T20:40:43.159509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Iterate over the labels_df\nfor index, row in labels_df.iterrows():\n    images = []\n    study_id = str(row['BraTS21ID']).zfill(5)\n    \n    # Get a list of one image from each series\n    for ser in series_names:\n        img_list, series_count = get_series_list(study_id, ser)\n        images.append([img_list,series_count])\n\n    # Iterate through the images list and check the plane of each\n    for img in images:\n\n        image = pydicom.dcmread(img[0])\n        \n        # Get the IOP tag for this image\n        image_orientation_patient = image[0x0020,0x0037]\n        \n        # Get the plane for this image/series\n        plane = get_image_plane(image_orientation_patient)\n\n        # Add the plane data to the labels dataframe\n        img_temp = img[0].split(\"/\")\n        labels_df.at[index,'plane_' + img_temp[5]] = plane\n        labels_df.at[index,'count_' + img_temp[5]] = img[1]","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:40:43.162113Z","iopub.execute_input":"2021-08-31T20:40:43.162568Z","iopub.status.idle":"2021-08-31T20:46:39.052196Z","shell.execute_reply.started":"2021-08-31T20:40:43.162521Z","shell.execute_reply":"2021-08-31T20:46:39.050374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels_df.head(50)","metadata":{"execution":{"iopub.status.busy":"2021-08-31T21:18:40.393248Z","iopub.execute_input":"2021-08-31T21:18:40.393730Z","iopub.status.idle":"2021-08-31T21:18:40.472537Z","shell.execute_reply.started":"2021-08-31T21:18:40.393632Z","shell.execute_reply":"2021-08-31T21:18:40.470994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### We see that most of the columns have different planes. Let's check unique values to see if *any* are in the same plane across the entire dataset.","metadata":{}},{"cell_type":"code","source":"print(\"FLAIR: \", labels_df['plane_FLAIR'].unique())\nprint(\"T1w: \", labels_df['plane_T1w'].unique())\nprint(\"T1wCE: \", labels_df['plane_T1wCE'].unique())\nprint(\"T2w: \", labels_df['plane_T2w'].unique())","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:46:39.094020Z","iopub.execute_input":"2021-08-31T20:46:39.094415Z","iopub.status.idle":"2021-08-31T20:46:39.110937Z","shell.execute_reply.started":"2021-08-31T20:46:39.094375Z","shell.execute_reply":"2021-08-31T20:46:39.109563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Now we can see that none of the series are all in the same plane, as they all have *some* series in each plane.\n\n- Export the updated labels dataframe to CSV.","metadata":{}},{"cell_type":"code","source":"labels_df.to_csv(\"train_labels_with_planes.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2021-08-31T20:46:39.112477Z","iopub.execute_input":"2021-08-31T20:46:39.112870Z","iopub.status.idle":"2021-08-31T20:46:39.127960Z","shell.execute_reply.started":"2021-08-31T20:46:39.112834Z","shell.execute_reply":"2021-08-31T20:46:39.126874Z"},"trusted":true},"execution_count":null,"outputs":[]}]}