{"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":"## Step 1. How to gather common ids and bounding-box infos?","metadata":{}},{"cell_type":"code","source":"# Required for some dicom files.\n!pip install -q ../input/for-pydicom/pylibjpeg-1.4.0-py3-none-any.whl\n!pip install -q ../input/for-pydicom/python_gdcm-3.0.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\n!pip install -q ../input/for-pydicom/pylibjpeg_libjpeg-1.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:16:36.465179Z","iopub.execute_input":"2022-08-02T04:16:36.4659Z","iopub.status.idle":"2022-08-02T04:17:12.640624Z","shell.execute_reply.started":"2022-08-02T04:16:36.465677Z","shell.execute_reply":"2022-08-02T04:17:12.639044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom glob import glob\n\nimport pandas as pd\nimport numpy as np\n\nimport cv2\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport nibabel as nib\nimport matplotlib.pyplot as plt\nplt.style.use('dark_background')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-08-02T04:17:12.644062Z","iopub.execute_input":"2022-08-02T04:17:12.644551Z","iopub.status.idle":"2022-08-02T04:17:13.345671Z","shell.execute_reply.started":"2022-08-02T04:17:12.644493Z","shell.execute_reply":"2022-08-02T04:17:13.344537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_folder = '../input/rsna-2022-cervical-spine-fracture-detection/'\nnii_dir = data_folder + 'segmentations/'\nbbox_path = data_folder + 'train_bounding_boxes.csv'\ndicom_train_dir = data_folder + 'train_images/'","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.347504Z","iopub.execute_input":"2022-08-02T04:17:13.348266Z","iopub.status.idle":"2022-08-02T04:17:13.355167Z","shell.execute_reply.started":"2022-08-02T04:17:13.348215Z","shell.execute_reply":"2022-08-02T04:17:13.353759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"nii_paths = glob(nii_dir + '*.nii')\nprint(f'counts: {len(nii_paths)}')\nprint(f'sample: {nii_paths[0]}')","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.359155Z","iopub.execute_input":"2022-08-02T04:17:13.359862Z","iopub.status.idle":"2022-08-02T04:17:13.388375Z","shell.execute_reply.started":"2022-08-02T04:17:13.359792Z","shell.execute_reply":"2022-08-02T04:17:13.387324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_bbox = pd.read_csv(bbox_path)\ndf_bbox","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.389975Z","iopub.execute_input":"2022-08-02T04:17:13.390614Z","iopub.status.idle":"2022-08-02T04:17:13.442384Z","shell.execute_reply.started":"2022-08-02T04:17:13.390575Z","shell.execute_reply":"2022-08-02T04:17:13.441396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_bbox['StudyInstanceUID'] = df_bbox['StudyInstanceUID'].astype('str')\ndf_bbox['slice_number'] = df_bbox['slice_number'].astype('str')\ndf_bbox['x_min'] = df_bbox['x'].astype('int64')\ndf_bbox['y_min'] = df_bbox['y'].astype('int64')\ndf_bbox['x_max'] = df_bbox['x_min'] + df_bbox['width'].astype('int64')\ndf_bbox['y_max'] = df_bbox['y_min'] + df_bbox['height'].astype('int64')\ndf_bbox.drop(['x','y','width','height'], axis=1, inplace=True)\ndf_bbox","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.443872Z","iopub.execute_input":"2022-08-02T04:17:13.444509Z","iopub.status.idle":"2022-08-02T04:17:13.483866Z","shell.execute_reply.started":"2022-08-02T04:17:13.444473Z","shell.execute_reply":"2022-08-02T04:17:13.482866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dicom_train_ids = [x.split('/')[-1] for x in glob(dicom_train_dir + '*')]\nprint(f'counts: {len(dicom_train_ids)}')\nprint(f'sample: {dicom_train_ids[0]}')\n\nisin_train_ids = df_bbox['StudyInstanceUID'].apply(lambda x : x if x in dicom_train_ids else None)\nprint(f'counts(id-null): {isin_train_ids.isna().sum()}')","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.485997Z","iopub.execute_input":"2022-08-02T04:17:13.487217Z","iopub.status.idle":"2022-08-02T04:17:13.788344Z","shell.execute_reply.started":"2022-08-02T04:17:13.487171Z","shell.execute_reply":"2022-08-02T04:17:13.787085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"nii_ids = [x.split('/')[-1][:-4] for x in nii_paths]\nprint(f'counts: {len(nii_ids)}')\nprint(f'sample: {nii_ids[0]}')\n\nisin_nii_ids = df_bbox['StudyInstanceUID'].apply(lambda x : x if x in nii_ids else None)\nprint(f'counts(id-null): {isin_nii_ids.isna().sum()}')","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.789974Z","iopub.execute_input":"2022-08-02T04:17:13.79046Z","iopub.status.idle":"2022-08-02T04:17:13.810875Z","shell.execute_reply.started":"2022-08-02T04:17:13.790419Z","shell.execute_reply":"2022-08-02T04:17:13.809562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_inter = df_bbox.iloc[isin_nii_ids.dropna().index]\ndf_inter.reset_index(drop=True, inplace=True)\ndf_inter","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.812474Z","iopub.execute_input":"2022-08-02T04:17:13.812873Z","iopub.status.idle":"2022-08-02T04:17:13.830786Z","shell.execute_reply.started":"2022-08-02T04:17:13.812811Z","shell.execute_reply":"2022-08-02T04:17:13.829781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Step 2. Draw some sample factures","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(12,12))\n\nfor i, row in df_inter.iterrows():\n    s_uid = row['StudyInstanceUID']\n    s_num = row['slice_number']\n    x_min = row['x_min']\n    x_max = row['x_max']\n    y_min = row['y_min']\n    y_max = row['y_max']\n    \n    nii = nib.load(nii_dir + s_uid + '.nii')\n    # (ref) discussion : Explaining Data and Submission in detail\n    nii = nii.get_fdata()[:, ::-1, ::-1].transpose(2,1,0)\n    nii = nii[int(s_num)]\n    \n    dicom = pydicom.read_file(dicom_train_dir + s_uid + f'/{s_num}.dcm')\n    dicom = dicom.pixel_array\n    dicom = (dicom - np.min(dicom)) / np.max(dicom)\n    dicom = (dicom * 255).astype(np.uint8)\n    dicom = cv2.cvtColor(dicom, cv2.COLOR_GRAY2RGB)\n    cv2.rectangle(dicom, pt1=(x_min, y_min), pt2=(x_max, y_max), color=(255,0,0), thickness=3)\n    if i <= 8:\n        ax = fig.add_subplot(int(f'33{i+1}'))\n        ax.imshow(nii, alpha=1, cmap='gray')\n        ax.imshow(dicom, alpha=0.45)\n        ax.set_title(f'sample({i+1})\\n')\n        ax.axis('off')\n    else:\n        break;\n        \nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:13.834066Z","iopub.execute_input":"2022-08-02T04:17:13.834781Z","iopub.status.idle":"2022-08-02T04:17:17.813987Z","shell.execute_reply.started":"2022-08-02T04:17:13.834739Z","shell.execute_reply":"2022-08-02T04:17:17.812576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Step 3. And.. Let's make Class","metadata":{}},{"cell_type":"code","source":"class DrawFracSample():\n    def __init__(self):\n        self.data_folder = '../input/rsna-2022-cervical-spine-fracture-detection/'\n        self.nii_dir = self.data_folder + 'segmentations/'\n        self.bbox_path = self.data_folder + 'train_bounding_boxes.csv'\n        self.dicom_train_dir = self.data_folder + 'train_images/'\n        \n        self.get_frac_info()\n        self.show_fractures()\n        \n    def get_frac_info(self):\n        df_bbox = pd.read_csv(self.bbox_path)\n        df_bbox['StudyInstanceUID'] = df_bbox['StudyInstanceUID'].astype('str')\n        df_bbox['slice_number'] = df_bbox['slice_number'].astype('str')\n        df_bbox['x_min'] = df_bbox['x'].astype('int64')\n        df_bbox['y_min'] = df_bbox['y'].astype('int64')\n        df_bbox['x_max'] = df_bbox['x_min'] + df_bbox['width'].astype('int64')\n        df_bbox['y_max'] = df_bbox['y_min'] + df_bbox['height'].astype('int64')\n        df_bbox.drop(['x','y','width','height'], axis=1, inplace=True)\n        \n        nii_paths = glob(self.nii_dir + '*.nii')\n        nii_ids = [x.split('/')[-1][:-4] for x in nii_paths]\n        isin_nii_ids = df_bbox['StudyInstanceUID'].apply(lambda x : x if x in nii_ids else None)\n        self.df_inter = df_bbox.iloc[isin_nii_ids.dropna().index]\n        self.df_inter.reset_index(drop=True, inplace=True)\n\n    def show_fractures(self, alp=0.45):\n        fig = plt.figure(figsize=(12,12))\n\n        # 10% randomly selected from a df_inter\n        df_sample = self.df_inter.sample(frac=0.1).reset_index(drop=True)\n        for i, row in df_sample.iterrows():\n            s_uid = row['StudyInstanceUID']\n            s_num = row['slice_number']\n            x_min = row['x_min']\n            x_max = row['x_max']\n            y_min = row['y_min']\n            y_max = row['y_max']\n\n            nii = nib.load(self.nii_dir + s_uid + '.nii')\n            # (ref) discussion : Explaining Data and Submission in detail\n            nii = nii.get_fdata()[:, ::-1, ::-1].transpose(2,1,0)\n            nii = nii[int(s_num)]\n\n            dicom = pydicom.read_file(self.dicom_train_dir + s_uid + f'/{s_num}.dcm')\n            \n            # we cannot load some of dicom file with this code. so we will use apply_voi_lut() for all.\n            #dicom = dicom.pixel_array\n            dicom = apply_voi_lut(dicom.pixel_array, dicom)\n            dicom = (dicom - np.min(dicom)) / np.max(dicom)\n            dicom = (dicom * 255).astype(np.uint8)\n            dicom = cv2.cvtColor(dicom, cv2.COLOR_GRAY2RGB)\n            cv2.rectangle(dicom, pt1=(x_min, y_min), pt2=(x_max, y_max), color=(255,0,0), thickness=3)\n            if i+1 <= 9:\n                ax = fig.add_subplot(int(f'33{i+1}'))\n                ax.imshow(nii, alpha=1, cmap='gray')\n                ax.imshow(dicom, alpha=alp)\n                ax.set_title(f'sample({i+1})\\n')\n                ax.axis('off')\n            else:\n                break;\n        plt.tight_layout()\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:17.815543Z","iopub.execute_input":"2022-08-02T04:17:17.816129Z","iopub.status.idle":"2022-08-02T04:17:17.834474Z","shell.execute_reply.started":"2022-08-02T04:17:17.816092Z","shell.execute_reply":"2022-08-02T04:17:17.8333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfs = DrawFracSample()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:17.836245Z","iopub.execute_input":"2022-08-02T04:17:17.837024Z","iopub.status.idle":"2022-08-02T04:17:33.210397Z","shell.execute_reply.started":"2022-08-02T04:17:17.836982Z","shell.execute_reply":"2022-08-02T04:17:33.209019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfs = DrawFracSample()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:33.211976Z","iopub.execute_input":"2022-08-02T04:17:33.212376Z","iopub.status.idle":"2022-08-02T04:17:43.189526Z","shell.execute_reply.started":"2022-08-02T04:17:33.212332Z","shell.execute_reply":"2022-08-02T04:17:43.188269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfs = DrawFracSample()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T04:17:43.191349Z","iopub.execute_input":"2022-08-02T04:17:43.191724Z","iopub.status.idle":"2022-08-02T04:17:51.674199Z","shell.execute_reply.started":"2022-08-02T04:17:43.191686Z","shell.execute_reply":"2022-08-02T04:17:51.67315Z"},"trusted":true},"execution_count":null,"outputs":[]}]}