{"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":"# NÃO","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport glob\nimport PIL\nimport shutil\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom skimage import data\nfrom skimage.util import montage \nimport skimage.transform as skTrans\nfrom skimage.transform import rotate\nfrom skimage.transform import resize\nfrom PIL import Image, ImageOps  \n\n# neural imaging\nimport nilearn as nl\nimport nibabel as nib\nimport nilearn.plotting as nlplt\n\n\n# ml libs\nimport keras\nimport keras.backend as K\nfrom keras.callbacks import CSVLogger\nimport tensorflow as tf\nfrom tensorflow.keras.utils import plot_model\nfrom sklearn.preprocessing import MinMaxScaler\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\nfrom tensorflow.keras.models import *\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.optimizers import *\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping, TensorBoard\nfrom tensorflow.keras.layers.experimental import preprocessing\n\n\n# Make numpy printouts easier to read.\nnp.set_printoptions(precision=3, suppress=True)\n# DEFINE seg-areas  \nSEGMENT_CLASSES = {\n    0 : 'NOT tumor',   \n    1 : 'NECROTIC/CORE', # or NON-ENHANCING tumor CORE - RED\n    2 : 'EDEMA',  # Green\n    3 : 'ENHANCING' # original 4 -> converted into 3 later, Yellow\n}\n\n# there are 155 slices per volume\n# to start at 5 and use 145 slices means we will skip the first 5 and last 5 \nVOLUME_SLICES = 100 \nVOLUME_START_AT = 22 # first slice of volume that we will include\n\nIMG_SIZE=128\nimport tarfile\nfile = tarfile.open('../input/brats-2021-task1/BraTS2021_Training_Data.tar')\n\nfile.extractall('./BraTS2021_Training_Data')\nfile.close()\nfile = tarfile.open('../input/brats-2021-task1/BraTS2021_00621.tar')\n\nfile.extractall('./sample_img')\nfile.close()","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:28:54.196499Z","iopub.execute_input":"2023-06-11T08:28:54.197140Z","iopub.status.idle":"2023-06-11T08:31:36.912898Z","shell.execute_reply.started":"2023-06-11T08:28:54.197098Z","shell.execute_reply":"2023-06-11T08:31:36.911881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file = tarfile.open('../input/brats-2021-task1/BraTS2021_00621.tar')\n\nfile.extractall('./sample_img')\nfile.close()\n\nnSample = os.listdir('./sample_img')\nnSample","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:31:36.914944Z","iopub.execute_input":"2023-06-11T08:31:36.915824Z","iopub.status.idle":"2023-06-11T08:31:36.953891Z","shell.execute_reply.started":"2023-06-11T08:31:36.915787Z","shell.execute_reply":"2023-06-11T08:31:36.953008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"########################################################################################################","metadata":{}},{"cell_type":"code","source":"TRAIN_DATASET_PATH = './BraTS2021_Training_Data/'\nnSample = os.listdir(TRAIN_DATASET_PATH + 'BraTS2021_01261')\nnSample","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:31:51.172469Z","iopub.execute_input":"2023-06-11T08:31:51.172819Z","iopub.status.idle":"2023-06-11T08:31:51.180553Z","shell.execute_reply.started":"2023-06-11T08:31:51.172791Z","shell.execute_reply":"2023-06-11T08:31:51.179657Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_image_flair=nib.load(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_flair.nii.gz').get_fdata()\ntest_image_t1=nib.load(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_t1.nii.gz').get_fdata()\ntest_image_t1ce=nib.load(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_t1ce.nii.gz').get_fdata()\ntest_image_t2=nib.load(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_t2.nii.gz').get_fdata()\ntest_mask=nib.load(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_seg.nii.gz').get_fdata()","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:32:06.207767Z","iopub.execute_input":"2023-06-11T08:32:06.208136Z","iopub.status.idle":"2023-06-11T08:32:06.948812Z","shell.execute_reply.started":"2023-06-11T08:32:06.208104Z","shell.execute_reply":"2023-06-11T08:32:06.947731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(1,5, figsize = (20, 10))\nslice_w = 25\nax1.imshow(test_image_flair[:,:,test_image_flair.shape[0]//2-slice_w], cmap = 'gray')\nax1.set_title('Image flair')\nax2.imshow(test_image_t1[:,:,test_image_t1.shape[0]//2-slice_w], cmap = 'gray')\nax2.set_title('Image t1')\nax3.imshow(test_image_t1ce[:,:,test_image_t1ce.shape[0]//2-slice_w], cmap = 'gray')\nax3.set_title('Image t1ce')\nax4.imshow(test_image_t2[:,:,test_image_t2.shape[0]//2-slice_w], cmap = 'gray')\nax4.set_title('Image t2')\nax5.imshow(test_mask[:,:,test_mask.shape[0]//2-slice_w])\nax5.set_title('Mask')","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:32:12.646807Z","iopub.execute_input":"2023-06-11T08:32:12.647347Z","iopub.status.idle":"2023-06-11T08:32:13.954955Z","shell.execute_reply.started":"2023-06-11T08:32:12.647309Z","shell.execute_reply":"2023-06-11T08:32:13.954000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax1 = plt.subplots(1, 1, figsize = (15,15))\nax1.imshow(rotate(montage(test_image_t1[50:-50,:,:]), 90, resize=True), cmap ='gray')","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:32:31.432028Z","iopub.execute_input":"2023-06-11T08:32:31.432502Z","iopub.status.idle":"2023-06-11T08:32:34.392458Z","shell.execute_reply.started":"2023-06-11T08:32:31.432461Z","shell.execute_reply":"2023-06-11T08:32:34.391592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax1 = plt.subplots(1, 1, figsize = (15,15))\nax1.imshow(rotate(montage(test_mask[60:-60,:,:]), 90, resize=True), cmap ='gray')","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:32:42.234382Z","iopub.execute_input":"2023-06-11T08:32:42.234969Z","iopub.status.idle":"2023-06-11T08:32:43.487815Z","shell.execute_reply.started":"2023-06-11T08:32:42.234932Z","shell.execute_reply":"2023-06-11T08:32:43.486910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"niimg = nl.image.load_img(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_flair.nii.gz')\nnimask = nl.image.load_img(TRAIN_DATASET_PATH + 'BraTS2021_01261/BraTS2021_01261_seg.nii.gz')\n\nfig, axes = plt.subplots(nrows=4, figsize=(30, 40))\n\n\nnlplt.plot_anat(niimg,\n                title='BraTS18_Training_001_flair.nii plot_anat',\n                axes=axes[0])\n\nnlplt.plot_epi(niimg,\n               title='BraTS18_Training_001_flair.nii plot_epi',\n               axes=axes[1])\n\nnlplt.plot_img(niimg,\n               title='BraTS18_Training_001_flair.nii plot_img',\n               axes=axes[2])\n\nnlplt.plot_roi(nimask, \n               title='BraTS18_Training_001_flair.nii with mask plot_roi',\n               bg_img=niimg, \n               axes=axes[3], cmap='Paired')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-11T08:32:53.221118Z","iopub.execute_input":"2023-06-11T08:32:53.221483Z","iopub.status.idle":"2023-06-11T08:33:06.307618Z","shell.execute_reply.started":"2023-06-11T08:32:53.221451Z","shell.execute_reply":"2023-06-11T08:33:06.306229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\nImport các thư viện cần thiết:","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tarfile\nimport plotly\nfrom plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:18:50.134194Z","iopub.execute_input":"2023-06-11T09:18:50.134575Z","iopub.status.idle":"2023-06-11T09:18:50.141790Z","shell.execute_reply.started":"2023-06-11T09:18:50.134545Z","shell.execute_reply":"2023-06-11T09:18:50.140922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Định nghĩa hàm extract_task1_files() để giải nén các tệp tin từ tệp tar:\n\nPhần đầu tiên chứa một hàm và một hàm trợ giúp để giải nén tệp tin từ một tệp tin nén (tar) và lưu chúng vào một thư mục cụ thể:\n\nextract_task1_files(root=\"./data\"): Hàm này nhận đầu vào là root (đường dẫn đến thư mục đích) và thực hiện việc giải nén các tệp tin từ tệp tin nén (tar) vào thư mục root.","metadata":{}},{"cell_type":"code","source":"def extract_task1_files(root=\"./data\"):\n    tar = tarfile.open(\"../input/brats-2021-task1/BraTS2021_Training_Data.tar\")\n    tar.extractall(root)\n    tar.close()","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:18:52.246846Z","iopub.execute_input":"2023-06-11T09:18:52.247190Z","iopub.status.idle":"2023-06-11T09:18:52.252139Z","shell.execute_reply.started":"2023-06-11T09:18:52.247162Z","shell.execute_reply":"2023-06-11T09:18:52.251214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"extract_task1_files()","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:18:54.940861Z","iopub.execute_input":"2023-06-11T09:18:54.941217Z","iopub.status.idle":"2023-06-11T09:20:46.107778Z","shell.execute_reply.started":"2023-06-11T09:18:54.941189Z","shell.execute_reply":"2023-06-11T09:20:46.106771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Định nghĩa lớp ImageReader để đọc và xử lý hình ảnh:\n\nPhần thứ hai chứa một lớp ImageReader và một hàm để tạo một đối tượng Scatter3d cho việc hiển thị dữ liệu ba chiều:\n\n**ImageReader**: Đây là một lớp có chức năng đọc và xử lý dữ liệu hình ảnh từ các tệp tin NIfTI. Lớp này có các thuộc tính như root (đường dẫn gốc), img_size (kích thước ảnh), normalize (có chuẩn hóa hình ảnh hay không), và single_class (sử dụng một lớp duy nhất hay không). Lớp này có các phương thức như read_file() (đọc và xử lý một tệp tin hình ảnh), và load_patient_scan() (tải dữ liệu hình ảnh cho một bệnh nhân cụ thể).","metadata":{}},{"cell_type":"code","source":"import nibabel as nib\nimport os\nimport albumentations as A\nimport numpy as np\n\n\nclass ImageReader:\n    def __init__(self, root:str, img_size:int=256, normalize:bool=False, single_class:bool=False):\n        pad_size = 256 if img_size > 256 else 224\n        self.resize = A.Compose(\n            [\n                A.PadIfNeeded(min_height=pad_size, min_width=pad_size, value=0),\n                A.Resize(img_size, img_size)\n            ]\n        )\n        self.normalize=normalize\n        self.single_class=single_class\n        self.root=root\n        \n    def read_file(self, path:str) -> dict:\n        scan_type = path.split('_')[-1]\n        raw_image = nib.load(path).get_fdata()\n        raw_mask = nib.load(path.replace(scan_type, 'seg.nii.gz')).get_fdata()\n        processed_frames, processed_masks = [], []\n        for frame_idx in range(raw_image.shape[2]):\n            frame = raw_image[:, :, frame_idx]\n            mask = raw_mask[:, :, frame_idx]\n            if self.normalize:\n                if frame.max() > 0:\n                    frame = frame/frame.max()\n                frame = frame.astype(np.float32)\n            else:\n                frame = frame.astype(np.uint8)\n            resized = self.resize(image=frame, mask=mask)\n            processed_frames.append(resized['image'])\n            processed_masks.append(1*(resized['mask'] > 0) if self.single_class else resized['mask'])\n        return {\n            'scan': np.stack(processed_frames, 0),\n            'segmentation': np.stack(processed_masks, 0),\n            'orig_shape': raw_image.shape\n        }\n    \n    def load_patient_scan(self, idx:int, scan_type:str='flair') -> dict:\n        patient_id = str(idx).zfill(5)\n        scan_filename = f'{self.root}/BraTS2021_{patient_id}/BraTS2021_{patient_id}_{scan_type}.nii.gz'\n        return self.read_file(scan_filename)","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:21:11.030503Z","iopub.execute_input":"2023-06-11T09:21:11.031030Z","iopub.status.idle":"2023-06-11T09:21:11.045461Z","shell.execute_reply.started":"2023-06-11T09:21:11.030998Z","shell.execute_reply":"2023-06-11T09:21:11.044038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.graph_objects as go\nimport numpy as np\n\n \n# generate_3d_scatter(): Đây là một hàm tạo một đối tượng Scatter3d của Plotly để hiển thị \n# dữ liệu ba chiều. \n# Hàm này nhận các thông số như x, y, z (các mảng dữ liệu tọa độ), colors (mảng màu sắc), \n# size (kích thước điểm), opacity (độ mờ), scale (bảng màu), hover (thông tin hiển thị khi \n# di chuột), và name (tên của đối tượng Scatter3d).\ndef generate_3d_scatter(\n    x:np.array, y:np.array, z:np.array, colors:np.array,\n    size:int=3, opacity:float=0.2, scale:str='Teal',\n    hover:str='skip', name:str='MRI'\n) -> go.Scatter3d:\n    return go.Scatter3d(\n        x=x, y=y, z=z,\n        mode='markers', hoverinfo=hover,\n        marker = dict(\n            size=size, opacity=opacity,\n            color=colors, colorscale=scale\n        ),\n        name=name\n    )\n\n\nclass ImageViewer3d():\n#     Hàm khởi tạo (__init__) của lớp ImageViewer3d nhận các tham số như reader \n#     (đối tượng ImageReader), mri_downsample (tỉ lệ mẫu giảm của hình ảnh MRI), \n#     và mri_colorscale (bảng màu cho hình ảnh MRI).\n    def __init__(self, reader:ImageReader, mri_downsample:int=10, mri_colorscale:str='Ice', voxel_size:float=0.1) -> None:\n        self.reader = reader\n        self.mri_downsample = mri_downsample\n        self.mri_colorscale = mri_colorscale\n        self.voxel_size = voxel_size\n        \n# Phương thức load_clean_mri() được sử dụng để tải dữ liệu hình ảnh MRI sau khi đã làm sạch. \n# Phương thức này nhận đầu vào là image (mảng numpy của hình ảnh) và orig_dim (kích thước gốc \n# của hình ảnh). Nó tính toán tọa độ x, y, z của các điểm trong hình ảnh MRI có giá trị lớn hơn \n# 0, sử dụng tỉ lệ mẫu giảm mri_downsample, và trả về một từ điển chứa thông tin về các tọa độ \n# và màu sắc của các điểm.\n    def load_clean_mri(self, image:np.array, orig_dim:int) -> dict:\n        shape_offset = image.shape[1]/orig_dim\n        z, x, y = (image > 0).nonzero()\n        # only (1/mri_downsample) is sampled for the resulting image\n        x, y, z = x[::self.mri_downsample], y[::self.mri_downsample], z[::self.mri_downsample]\n        colors = image[z, x, y]\n        return dict(x=x/shape_offset, y=y/shape_offset, z=z, colors=colors)\n    \n# Phương thức load_tumor_segmentation() được sử dụng để tải dữ liệu phân-segmentation của khối u.\n# Phương thức này nhận đầu vào là image (mảng numpy của phân đoạn) và orig_dim (kích thước gốc\n# của hình ảnh). Nó tính toán tọa độ x, y, z của các điểm trong phân đoạn có giá trị tương ứng \n# với các lớp khối u, sử dụng các tỉ lệ mẫu giảm khác nhau (1/1, 1/3, 1/5) cho từng lớp, và trả \n# về một từ điển chứa thông tin về các tọa độ và màu sắc của các điểm.\n    def load_tumor_segmentation(self, image:np.array, orig_dim:int) -> dict:\n        tumors = {}\n        shape_offset = image.shape[1]/orig_dim\n        # 1/1, 1/3 and 1/5 pixels for tumor tissue classes 1(core), 2(invaded) and 4(enhancing)\n        sampling = {\n            1: 1, 2: 3, 4: 5\n        }\n        for class_idx in sampling:\n            z, x, y = (image == class_idx).nonzero()\n            x, y, z = x[::sampling[class_idx]], y[::sampling[class_idx]], z[::sampling[class_idx]]\n            tumors[class_idx] = dict(\n                x=x/shape_offset, y=y/shape_offset, z=z,\n                colors=class_idx/4\n            )\n        return tumors\n\n    \n# Hàm collect_patient_data trong đoạn mã trên được sử dụng để thu thập dữ liệu từ bệnh nhân và \n# tính toán các thông số liên quan đến kích thước và phân bố của các phần trong ảnh MRI.\n# Đầu tiên, hàm này tải ảnh MRI sạch (clean_mri) và thông tin phân đoạn của các loại u án UT \n# (tumors) từ đối số scan. Ảnh MRI sạch và thông tin phân đoạn được lưu trữ trong các biến \n# clean_mri và tumors tương ứng.\n# Tiếp theo, kích thước của một voxel được tính bằng cách lấy lũy thừa ba của kích thước voxel \n# (self.voxel_size). Biến voxel_volume lưu trữ kích thước voxel.\n# Biến markers_created được tính bằng tổng số điểm trong ảnh MRI sạch và tất cả các phân đoạn u\n# án UT trong tumors. Điều này đại diện cho tổng số điểm được tạo ra để hiển thị các phần trên \n# hình ảnh 3D.\n# Tiếp theo, số lượng điểm trong từng phần (ảnh MRI sạch, lõi u án UT, mô xung quanh bị xâm lấn \n# bởi u án UT, u án UT tăng cường) được tính bằng cách lấy kích thước của mỗi mảng dữ liệu từ \n# clean_mri và tumors và sử dụng thuộc tính .shape[0].\n# Sau đó, tỉ lệ phần trăm số điểm của từng phần được tính bằng cách chia số điểm của phần đó \n# cho markers_created và nhân với 100. Kết quả được lưu trong các biến clean_mri_tile, \n# tumor1_tile, tumor2_tile, và tumor4_tile.\n# Tiếp theo, kích thước của từng phần được tính bằng cách nhân số điểm trong phần đó với \n# voxel_volume và được lưu trữ trong các biến clean_mri_kichthuoc, tumor1_kichthuoc, \n# tumor2_kichthuoc, và tumor4_kichthuoc.\n# Sau đó, thông tin về số điểm và kích thước của từng phần được in ra màn hình sử dụng \n# câu lệnh print.\n# Cuối cùng, hàm trả về một danh sách chứa các đối tượng generate_3d_scatter tương ứng \n# với các phần và số lượng markers_created. Các đối tượng generate_3d_scatter này được \n# sử dụng để hiển thị các phần trên hình ảnh 3D.\n    def collect_patient_data(self, scan:dict) -> tuple:\n        clean_mri = self.load_clean_mri(scan['scan'], scan['orig_shape'][0])\n        tumors = self.load_tumor_segmentation(scan['segmentation'], scan['orig_shape'][0])\n        \n        voxel_volume = self.voxel_size ** 3\n        markers_created = clean_mri['x'].shape[0] + sum(tumors[class_idx]['x'].shape[0] for class_idx in tumors)\n        \n        clean_mri_diem = clean_mri['x'].shape[0]\n        tumor1_diem = tumors[1]['x'].shape[0]\n        tumor2_diem = tumors[2]['x'].shape[0]\n        tumor4_diem = tumors[4]['x'].shape[0]\n        \n        clean_mri_tile = round(clean_mri_diem /markers_created*100, 2)\n        tumor1_tile = round(tumor1_diem /markers_created*100, 2)\n        tumor2_tile = round(tumor2_diem /markers_created*100, 2)\n        tumor4_tile = round(tumor4_diem /markers_created*100, 2)\n \n        clean_mri_kichthuoc = str(round(clean_mri_diem * voxel_volume, 2)) + ' cm^3'\n        tumor1_kichthuoc = str(round(tumor1_diem * voxel_volume, 2)) + ' cm^3'\n        tumor2_kichthuoc = str(round(tumor2_diem * voxel_volume, 2)) + ' cm^3'\n        tumor4_kichthuoc = str(round(tumor4_diem * voxel_volume, 2)) + ' cm^3'\n        \n        print('Brain MRI - hình ảnh MRI sạch:', clean_mri_diem ,'points,', clean_mri_tile ,'%',clean_mri_kichthuoc)\n        print('Lõi u án UT:', tumor1_diem , 'points,', tumor1_tile ,'%,', tumor1_kichthuoc)\n        print('Mô xung quanh bị xâm lấn bởi u án UT:', tumor2_diem ,'points,', tumor2_tile ,'%,', tumor2_kichthuoc)\n        print('U án UT tăng cường bằng chất có chứa Gadolinium:', tumor4_diem ,'points,', tumor4_tile,'%,', tumor4_kichthuoc)\n        \n        return [\n            generate_3d_scatter(**clean_mri, scale=self.mri_colorscale, opacity=0.3, hover='skip', name='Brain MRI - hình ảnh MRI sạch('+ clean_mri_kichthuoc +')'),\n            generate_3d_scatter(**tumors[1], opacity=0.8, hover='all', name='Lõi u án UT(' + tumor1_kichthuoc + ')'),\n            generate_3d_scatter(**tumors[2], opacity=0.4, hover='all', name='Mô xung quanh bị xâm lấn bởi u án UT(' + tumor2_kichthuoc + ')'),\n            generate_3d_scatter(**tumors[4], opacity=0.4, hover='all', name='U án UT tăng cường bằng chất có chứa Gadolinium(' + tumor4_kichthuoc + ')'),\n        ], markers_created\n \n\n# Phương thức get_3d_scan() được sử dụng để lấy dữ liệu ba chiều của một bệnh nhân và tạo đối \n# tượng biểu đồ Scatter3d tương ứng. Phương thức này nhận các đối số như patient_idx \n# (số thứ tự của bệnh nhân), và scan_type (loại quét MRI). Nó sử dụng phương thức \n# load_patient_scan() của lớp ImageReader để tải dữ liệu hình ảnh cho bệnh nhân cụ thể.\n# Sau đó, nó sử dụng phương thức collect_patient_data() để thu thập dữ liệu hình ảnh và \n# phân đoạn của bệnh nhân. Cuối cùng, nó tạo một đối tượng biểu đồ Scatter3d bằng cách sử \n# dụng các đối tượng Scatter3d từ dữ liệu thu thập và cài đặt các thuộc tính và cấu hình \n# cho biểu đồ Scatter3d và trả về đối tượng biểu đồ.\n    def get_3d_scan(self, patient_idx:int, scan_type:str='flair') -> go.Figure:\n        scan = self.reader.load_patient_scan(patient_idx, scan_type)\n        data, num_markers = self.collect_patient_data(scan)\n        fig = go.Figure(data=data)\n        fig.update_layout(\n            title=f\"[Patient id:{patient_idx}] brain MRI scan ({num_markers} points)\",\n            legend_title=\"Pixel class (click to enable/disable)\",\n            font=dict(\n                family=\"Courier New, monospace\",\n                size=14,\n            ),\n            margin=dict(\n                l=0,r=0,b=0,t=30\n            ),\n            legend=dict(itemsizing='constant')\n        )\n        return fig","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:21:17.200636Z","iopub.execute_input":"2023-06-11T09:21:17.200991Z","iopub.status.idle":"2023-06-11T09:21:17.234762Z","shell.execute_reply.started":"2023-06-11T09:21:17.200958Z","shell.execute_reply":"2023-06-11T09:21:17.233633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"reader = ImageReader('./data', img_size=128, normalize=True, single_class=False)\nviewer = ImageViewer3d(reader, mri_downsample=25)","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:21:21.654530Z","iopub.execute_input":"2023-06-11T09:21:21.654901Z","iopub.status.idle":"2023-06-11T09:21:21.659978Z","shell.execute_reply.started":"2023-06-11T09:21:21.654872Z","shell.execute_reply":"2023-06-11T09:21:21.658849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = viewer.get_3d_scan(0, 't1')\nplotly.offline.iplot(fig)\n","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:21:23.993202Z","iopub.execute_input":"2023-06-11T09:21:23.993560Z","iopub.status.idle":"2023-06-11T09:21:24.433155Z","shell.execute_reply.started":"2023-06-11T09:21:23.993533Z","shell.execute_reply":"2023-06-11T09:21:24.432373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = viewer.get_3d_scan(9, 'flair')\nplotly.offline.iplot(fig)","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:21:32.881326Z","iopub.execute_input":"2023-06-11T09:21:32.882182Z","iopub.status.idle":"2023-06-11T09:21:33.224982Z","shell.execute_reply.started":"2023-06-11T09:21:32.882139Z","shell.execute_reply":"2023-06-11T09:21:33.224078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport cv2\nimport glob\nimport PIL\nimport shutil\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom skimage import data\nfrom skimage.util import montage \nimport skimage.transform as skTrans\nfrom skimage.transform import rotate\nfrom skimage.transform import resize\nfrom PIL import Image, ImageOps  \n\n# neural imaging\nimport nilearn as nl\nimport nibabel as nib\nimport nilearn.plotting as nlplt\n\n\n# ml libs\nimport keras\nimport keras.backend as K\nfrom keras.callbacks import CSVLogger\nimport tensorflow as tf\nfrom tensorflow.keras.utils import plot_model\nfrom sklearn.preprocessing import MinMaxScaler\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\nfrom tensorflow.keras.models import *\nfrom tensorflow.keras.layers import *\nfrom tensorflow.keras.optimizers import *\nfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping, TensorBoard\nfrom tensorflow.keras.layers.experimental import preprocessing\n\n\n# Make numpy printouts easier to read.\nnp.set_printoptions(precision=3, suppress=True)\n# DEFINE seg-areas  \nSEGMENT_CLASSES = {\n    0 : 'NOT tumor',   \n    1 : 'NECROTIC/CORE', # or NON-ENHANCING tumor CORE - RED\n    2 : 'EDEMA',  # Green\n    3 : 'ENHANCING' # original 4 -> converted into 3 later, Yellow\n}\n\n# there are 155 slices per volume\n# to start at 5 and use 145 slices means we will skip the first 5 and last 5 \nVOLUME_SLICES = 100 \nVOLUME_START_AT = 22 # first slice of volume that we will include\n\nIMG_SIZE=128","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:27:37.364926Z","iopub.execute_input":"2023-06-11T09:27:37.365608Z","iopub.status.idle":"2023-06-11T09:27:49.863566Z","shell.execute_reply.started":"2023-06-11T09:27:37.365574Z","shell.execute_reply":"2023-06-11T09:27:49.862509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tarfile\nfile = tarfile.open('../input/brats-2021-task1/BraTS2021_Training_Data.tar')\n\nfile.extractall('./BraTS2021_Training_Data')\nfile.close()\nfile = tarfile.open('../input/brats-2021-task1/BraTS2021_00621.tar')\n\nfile.extractall('./sample_img')\nfile.close()","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:25:01.052603Z","iopub.execute_input":"2023-06-11T09:25:01.052965Z","iopub.status.idle":"2023-06-11T09:26:59.718268Z","shell.execute_reply.started":"2023-06-11T09:25:01.052932Z","shell.execute_reply":"2023-06-11T09:26:59.717256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file = tarfile.open('../input/brats-2021-task1/BraTS2021_00621.tar')\n\nfile.extractall('./sample_img')\nfile.close()\n\nnSample = os.listdir('./sample_img')\nnSample","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:27:56.766700Z","iopub.execute_input":"2023-06-11T09:27:56.767468Z","iopub.status.idle":"2023-06-11T09:27:56.799398Z","shell.execute_reply.started":"2023-06-11T09:27:56.767434Z","shell.execute_reply":"2023-06-11T09:27:56.798328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_DATASET_PATH = './BraTS2021_Training_Data/'\nnSample = os.listdir(TRAIN_DATASET_PATH + 'BraTS2021_01261')\nnSample","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:27:59.936094Z","iopub.execute_input":"2023-06-11T09:27:59.936536Z","iopub.status.idle":"2023-06-11T09:27:59.944702Z","shell.execute_reply.started":"2023-06-11T09:27:59.936496Z","shell.execute_reply":"2023-06-11T09:27:59.943714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\nimg_id = \"00009\"\ndata_dir = '/kaggle/working/BraTS2021_Training_Data'\n\nfor i, nii in enumerate([os.path.join(data_dir, f'BraTS2021_{img_id}/BraTS2021_{img_id}_{s_type}.nii.gz') for s_type in [\"flair\", \"t1\", \"t1ce\", \"t2\", \"seg\"]]):\n    # PLOTTING\n    image = nib.load(nii).get_fdata()\n    slices = image.shape[-1]\n    rows = int(np.ceil((slices/2)/10))\n    fig, axs = plt.subplots(rows, 10, figsize=(20, rows*2))\n    fig.suptitle(f\"\\n\\n\\n{nii.rsplit('_', 1)[-1].split('.', 1)[0]} SCAN\\n\".upper(), fontsize=18, fontweight=\"bold\")\n    \n    folder_name = os.path.basename(os.path.dirname(nii))\n    fig.text(0.5, 0.95, folder_name, horizontalalignment='center', verticalalignment='center', fontsize=12)\n    \n    for j, ax in enumerate(axs.flat):\n        if j*2 < slices:\n            ax.imshow(image[:, :, j*2], cmap=\"bone\")\n            ax.axis('off')\n        else:\n            ax.remove()  # Remove extra empty axes\n        \n    plt.tight_layout()\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-06-11T09:37:46.362839Z","iopub.execute_input":"2023-06-11T09:37:46.363232Z","iopub.status.idle":"2023-06-11T09:38:04.925824Z","shell.execute_reply.started":"2023-06-11T09:37:46.363200Z","shell.execute_reply":"2023-06-11T09:38:04.923262Z"},"trusted":true},"execution_count":null,"outputs":[]}]}