{"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":"code","source":"import pydicom\nimport numpy as np\nimport os\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-13T12:14:13.039303Z","iopub.execute_input":"2021-08-13T12:14:13.040039Z","iopub.status.idle":"2021-08-13T12:14:13.476397Z","shell.execute_reply.started":"2021-08-13T12:14:13.039938Z","shell.execute_reply":"2021-08-13T12:14:13.475079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:14:28.334070Z","iopub.execute_input":"2021-08-25T02:14:28.334465Z","iopub.status.idle":"2021-08-25T02:16:14.441851Z","shell.execute_reply.started":"2021-08-25T02:14:28.334416Z","shell.execute_reply":"2021-08-25T02:16:14.440948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.getcwd()","metadata":{"execution":{"iopub.status.busy":"2021-08-13T12:14:16.617155Z","iopub.execute_input":"2021-08-13T12:14:16.617533Z","iopub.status.idle":"2021-08-13T12:14:16.626487Z","shell.execute_reply.started":"2021-08-13T12:14:16.617499Z","shell.execute_reply":"2021-08-13T12:14:16.625426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## STEP 1 : Confirmation of equality between csv file list and real file list","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport os\n\nROOT_PATH = \"../input/rsna-miccai-brain-tumor-radiogenomic-classification/\"\n\n# List of csv file\nori_DF = pd.read_csv(f'{ROOT_PATH}/'+'train_labels.csv')\nidx_list = ori_DF['BraTS21ID'].tolist()\n\nstr_idx_list = []\nfor elem in idx_list:\n    str_idx = str(elem).zfill(5)\n    str_idx_list.append(str_idx)\n\n# List from directory\nreal_idx = os.listdir(f'{ROOT_PATH}'+'train/') # ['00000', '00002',...\n\n### result\nif sorted(str_idx_list) == sorted(real_idx):\n    print(\"All same, no problem\")\nelse:\n    print(\"Something is wrong.!!!\")","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:46.797738Z","iopub.execute_input":"2021-08-12T11:05:46.798049Z","iopub.status.idle":"2021-08-12T11:05:46.825453Z","shell.execute_reply.started":"2021-08-12T11:05:46.79802Z","shell.execute_reply":"2021-08-12T11:05:46.824308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# STEP 2 : Making dataframe","metadata":{}},{"cell_type":"code","source":"df_list = []\nSEQ_MRI = ['FLAIR', 'T1w', 'T1wCE', 'T2w']\n\nfor idx in real_idx:\n    tmp_list = []\n\n    tmp_list.append(idx)\n    for seq_dir in SEQ_MRI:\n        fullname_path = f'{ROOT_PATH}/train/{idx}/{seq_dir}'\n        name_seq = f'n{seq_dir}'\n        nSeq = len(os.listdir(fullname_path))\n        f = pydicom.dcmread(f'{fullname_path}/{os.listdir(fullname_path)[0]}')\n        size_img = (f.Rows, f.Columns)        \n\n        tmp_list.append(seq_dir)\n        tmp_list.append(nSeq)\n        tmp_list.append(size_img)\n        tmp_list.append(f.ImageOrientationPatient)\n    df_list.append(tmp_list)\n\nprint(df_list[10])\nprint(np.shape(df_list))","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:46.827264Z","iopub.execute_input":"2021-08-12T11:05:46.827553Z","iopub.status.idle":"2021-08-12T11:05:59.544811Z","shell.execute_reply.started":"2021-08-12T11:05:46.827526Z","shell.execute_reply":"2021-08-12T11:05:59.543149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx, elem in enumerate(df_list):\n    df_list[idx][0] = int(elem[0])","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.547039Z","iopub.execute_input":"2021-08-12T11:05:59.547464Z","iopub.status.idle":"2021-08-12T11:05:59.555967Z","shell.execute_reply.started":"2021-08-12T11:05:59.547422Z","shell.execute_reply":"2021-08-12T11:05:59.554765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"col_name = ['BraTS21ID',\n            'seq1', 'num1', 'size1', 'ori1',\n            'seq2', 'num2', 'size2', 'ori2',\n            'seq3', 'num3', 'size3', 'ori3',\n            'seq4', 'num4', 'size4', 'ori4']\nexp_df = pd.DataFrame(df_list, columns=col_name)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.559924Z","iopub.execute_input":"2021-08-12T11:05:59.560429Z","iopub.status.idle":"2021-08-12T11:05:59.577482Z","shell.execute_reply.started":"2021-08-12T11:05:59.56038Z","shell.execute_reply":"2021-08-12T11:05:59.576048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df = pd.merge(basic_df, exp_df, how='left', on='BraTS21ID')","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.580013Z","iopub.execute_input":"2021-08-12T11:05:59.580442Z","iopub.status.idle":"2021-08-12T11:05:59.605417Z","shell.execute_reply.started":"2021-08-12T11:05:59.5804Z","shell.execute_reply":"2021-08-12T11:05:59.602308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(result_df.head())","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.609144Z","iopub.execute_input":"2021-08-12T11:05:59.609644Z","iopub.status.idle":"2021-08-12T11:05:59.637607Z","shell.execute_reply.started":"2021-08-12T11:05:59.609593Z","shell.execute_reply":"2021-08-12T11:05:59.636205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df.sum()","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.638882Z","iopub.execute_input":"2021-08-12T11:05:59.639213Z","iopub.status.idle":"2021-08-12T11:05:59.671666Z","shell.execute_reply.started":"2021-08-12T11:05:59.639184Z","shell.execute_reply":"2021-08-12T11:05:59.670737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# STEP 2 : orientation","metadata":{}},{"cell_type":"code","source":"import math","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.67434Z","iopub.execute_input":"2021-08-12T11:05:59.674715Z","iopub.status.idle":"2021-08-12T11:05:59.67837Z","shell.execute_reply.started":"2021-08-12T11:05:59.674648Z","shell.execute_reply":"2021-08-12T11:05:59.677681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"https://dicom.innolitics.com/ciods/rt-dose/image-plane/00200037\n\norientation = [cos(nxx),cos(nxy),cos(nxz),cos(nyx),cos(nyy),cos(nyz)]\n\ncosine graph (y axis) : 1 -> 0 -> -1\n\ndegree(x axis) : 0 degree, 90 degree, 180 degree\n\nradian(x axis) : 0 rad, pi/2 rad, pi rad\n\nround -> 1 = 0~45 degree, 0 = 45 ~ 135 degree, -1 = 135 ~ 180 degree\n\nrad -> 1 = 0 ~ pi/4 rad, 0 = pi/4 ~ 3 * pi/4 rad, -1 = 3 * pi/4 ~ pi","metadata":{}},{"cell_type":"code","source":"qtr_1 = math.pi / 4\nqtr_3 = 3 * math.pi / 4\npi_val = math.pi\n\nprint(\"    pi/4 = \", qtr_1)\nprint(\" 3* pi/4 = \", qtr_3)\nprint(\"    pi   = \", pi_val)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.679862Z","iopub.execute_input":"2021-08-12T11:05:59.680148Z","iopub.status.idle":"2021-08-12T11:05:59.696045Z","shell.execute_reply.started":"2021-08-12T11:05:59.680122Z","shell.execute_reply":"2021-08-12T11:05:59.694791Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cos_qtr1 = math.cos(math.pi/4)\ncos_qtr3 = math.cos(3*math.pi/4)\n\nprint(\"cos( 45deg)= \", cos_qtr1)\nprint(\"cos(135deg)= \", cos_qtr3)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.697471Z","iopub.execute_input":"2021-08-12T11:05:59.697784Z","iopub.status.idle":"2021-08-12T11:05:59.708043Z","shell.execute_reply.started":"2021-08-12T11:05:59.697753Z","shell.execute_reply":"2021-08-12T11:05:59.707084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"1~\", cos_qtr1, \" = 1\")\nprint(cos_qtr1, \" ~ \", cos_qtr3, \" = 0\")\nprint(cos_qtr3, \" ~ -1 = 0\")","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.709291Z","iopub.execute_input":"2021-08-12T11:05:59.709696Z","iopub.status.idle":"2021-08-12T11:05:59.721443Z","shell.execute_reply.started":"2021-08-12T11:05:59.709663Z","shell.execute_reply":"2021-08-12T11:05:59.720289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ori_list = [\"ori1\", \"ori2\", \"ori3\", \"ori4\"]","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.722683Z","iopub.execute_input":"2021-08-12T11:05:59.723041Z","iopub.status.idle":"2021-08-12T11:05:59.732053Z","shell.execute_reply.started":"2021-08-12T11:05:59.723013Z","shell.execute_reply":"2021-08-12T11:05:59.730912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import copy\n\nresult_df2 = copy.copy(result_df)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.733714Z","iopub.execute_input":"2021-08-12T11:05:59.734134Z","iopub.status.idle":"2021-08-12T11:05:59.743994Z","shell.execute_reply.started":"2021-08-12T11:05:59.734098Z","shell.execute_reply":"2021-08-12T11:05:59.743016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math\nfor ori_idx in ori_list:\n    for i in range(len(result_df2[ori_idx])):\n        tmp = []\n    #     print(result_df2[\"BraTS21ID\"][i], \"  \", result_df2[\"ori1\"][i], end='\\r')\n        tmp = list(result_df2[ori_idx][i])\n        result_df2[ori_idx][i] = tmp\n        for idx, j in enumerate(tmp):\n            tmp_2 = float(j)\n            if tmp_2 > math.cos(math.pi/4):\n                tmp_2 = 1\n            if tmp_2 <= math.cos(math.pi/4) and tmp_2 >= math.cos(3*math.pi/4):\n                tmp_2 = 0\n            if tmp_2 < math.cos(3*math.pi/4):\n                tmp_2 = -1\n            else:\n                pass\n    #             tmp_2 = \"unknown\"\n            tmp[idx] = tmp_2\n        result_df2[ori_idx][i] = tmp","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:05:59.745635Z","iopub.execute_input":"2021-08-12T11:05:59.745993Z","iopub.status.idle":"2021-08-12T11:06:02.252433Z","shell.execute_reply.started":"2021-08-12T11:05:59.745963Z","shell.execute_reply":"2021-08-12T11:06:02.25127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(result_df2)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.253798Z","iopub.execute_input":"2021-08-12T11:06:02.254115Z","iopub.status.idle":"2021-08-12T11:06:02.286729Z","shell.execute_reply.started":"2021-08-12T11:06:02.254085Z","shell.execute_reply":"2021-08-12T11:06:02.285636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sum = 0\nfor idx in range(len(result_df2)):\n    for ori_idx in ori_list:\n        tmp_list = result_df2[ori_idx][idx]\n        for elem in tmp_list:\n            if elem == 1 or elem == 0 or elem == -1 or elem == -0:\n                pass\n            else:\n                sum += 1","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.288082Z","iopub.execute_input":"2021-08-12T11:06:02.28839Z","iopub.status.idle":"2021-08-12T11:06:02.320759Z","shell.execute_reply.started":"2021-08-12T11:06:02.288353Z","shell.execute_reply":"2021-08-12T11:06:02.319731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sum","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.322091Z","iopub.execute_input":"2021-08-12T11:06:02.32239Z","iopub.status.idle":"2021-08-12T11:06:02.327741Z","shell.execute_reply.started":"2021-08-12T11:06:02.322355Z","shell.execute_reply":"2021-08-12T11:06:02.32673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(result_df2)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.329133Z","iopub.execute_input":"2021-08-12T11:06:02.329583Z","iopub.status.idle":"2021-08-12T11:06:02.369252Z","shell.execute_reply.started":"2021-08-12T11:06:02.329554Z","shell.execute_reply":"2021-08-12T11:06:02.36812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df2[\"ori1re\"] = result_df2[\"ori1\"]\nresult_df2[\"ori2re\"] = result_df2[\"ori2\"]\nresult_df2[\"ori3re\"] = result_df2[\"ori3\"]\nresult_df2[\"ori4re\"] = result_df2[\"ori4\"]","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.370569Z","iopub.execute_input":"2021-08-12T11:06:02.370856Z","iopub.status.idle":"2021-08-12T11:06:02.378368Z","shell.execute_reply.started":"2021-08-12T11:06:02.370829Z","shell.execute_reply":"2021-08-12T11:06:02.377165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(result_df2)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.379876Z","iopub.execute_input":"2021-08-12T11:06:02.380195Z","iopub.status.idle":"2021-08-12T11:06:02.432814Z","shell.execute_reply.started":"2021-08-12T11:06:02.380166Z","shell.execute_reply":"2021-08-12T11:06:02.431886Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Thanks to https://www.kaggle.com/arnabs007/part-1-rsna-miccai-btrc-understanding-the-data for analysis of image orientation.","metadata":{}},{"cell_type":"code","source":"orire_list = [\"ori1re\", \"ori2re\", \"ori3re\", \"ori4re\"]","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.433812Z","iopub.execute_input":"2021-08-12T11:06:02.43421Z","iopub.status.idle":"2021-08-12T11:06:02.443742Z","shell.execute_reply.started":"2021-08-12T11:06:02.434157Z","shell.execute_reply":"2021-08-12T11:06:02.442711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx in range(len(result_df2)):\n    for ori_idx in orire_list:\n        tmp_list = result_df2[ori_idx][idx]\n        coords = [tmp_list[0], tmp_list[1], tmp_list[3], tmp_list[4]]\n#         print(coords)\n        if coords == [1, 0, 0, 0]:\n            result_df2[ori_idx][idx] = \"coronal\"\n        elif coords == [1, 0, 0, 1]:\n            result_df2[ori_idx][idx] = \"axial\"\n        elif coords == [0, 1, 0, 0]:\n            result_df2[ori_idx][idx] = \"sagittal\"\n        else:\n            result_df2[ori_idx][idx] = \"unknown\"","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:02.445122Z","iopub.execute_input":"2021-08-12T11:06:02.445436Z","iopub.status.idle":"2021-08-12T11:06:03.622046Z","shell.execute_reply.started":"2021-08-12T11:06:02.445405Z","shell.execute_reply":"2021-08-12T11:06:03.62112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"raw","source":"print(result_df2)","metadata":{"execution":{"iopub.status.busy":"2021-08-12T10:58:32.726109Z","iopub.execute_input":"2021-08-12T10:58:32.726435Z","iopub.status.idle":"2021-08-12T10:58:32.770673Z","shell.execute_reply.started":"2021-08-12T10:58:32.726405Z","shell.execute_reply":"2021-08-12T10:58:32.769725Z"}}},{"cell_type":"code","source":"for idx in orire_list:\n    print(idx, \" = \",result_df2[idx].unique())","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:03.625736Z","iopub.execute_input":"2021-08-12T11:06:03.62606Z","iopub.status.idle":"2021-08-12T11:06:03.633736Z","shell.execute_reply.started":"2021-08-12T11:06:03.626029Z","shell.execute_reply":"2021-08-12T11:06:03.632817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Q1. How to deal with the variable image size among index?\n### Q2. How to process the images with variable file numbers?\n### Q3. How to process the images with several other orientations(coronal, axial, sagittal)?","metadata":{}},{"cell_type":"code","source":"result_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:03.634996Z","iopub.execute_input":"2021-08-12T11:06:03.635273Z","iopub.status.idle":"2021-08-12T11:06:03.67649Z","shell.execute_reply.started":"2021-08-12T11:06:03.635247Z","shell.execute_reply":"2021-08-12T11:06:03.67554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result_df2.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:03.6776Z","iopub.execute_input":"2021-08-12T11:06:03.677873Z","iopub.status.idle":"2021-08-12T11:06:03.73002Z","shell.execute_reply.started":"2021-08-12T11:06:03.677847Z","shell.execute_reply":"2021-08-12T11:06:03.728922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sorted(result_df['size4'].unique())","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:06:03.734126Z","iopub.execute_input":"2021-08-12T11:06:03.734832Z","iopub.status.idle":"2021-08-12T11:06:03.748056Z","shell.execute_reply.started":"2021-08-12T11:06:03.734782Z","shell.execute_reply":"2021-08-12T11:06:03.747046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# thanks to https://www.kaggle.com/josecarmona/btrc-a-simple-tool-to-crop-3d-images","metadata":{}},{"cell_type":"code","source":"import numpy as np \nfrom glob import glob\nimport pydicom\nimport matplotlib.pyplot as plt\nimport plotly.express as px\n\ndef read_dicom_files(cohort, case, SEQ_MRI):\n    ROOT_PATH = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\n    files_glob = f'{ROOT_PATH}/{cohort}/{case}/{SEQ_MRI}/*.dcm'\n    sorted_files = sorted(glob(files_glob),key=lambda f: int(f.split('Image-')[1].split('.')[0]))\n    return [pydicom.read_file(f) for f in sorted_files]","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:08:57.141613Z","iopub.execute_input":"2021-08-12T11:08:57.142054Z","iopub.status.idle":"2021-08-12T11:08:58.869029Z","shell.execute_reply.started":"2021-08-12T11:08:57.142014Z","shell.execute_reply":"2021-08-12T11:08:58.867691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def cropped_images(images):\n    min=np.array(np.nonzero(images)).min(axis=1)\n    max=np.array(np.nonzero(images)).max(axis=1)\n    return images[min[0]:max[0],min[1]:max[1],min[2]:max[2]]","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:09:00.098832Z","iopub.execute_input":"2021-08-12T11:09:00.099257Z","iopub.status.idle":"2021-08-12T11:09:00.104807Z","shell.execute_reply.started":"2021-08-12T11:09:00.099221Z","shell.execute_reply":"2021-08-12T11:09:00.103962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cohort = 'train'\ncase = '00000'\nmpMRI = 'FLAIR'\ndicom_files = read_dicom_files(cohort, case, mpMRI)\n\nimages = np.array([s.pixel_array for s in dicom_files])\nimages = cropped_images(images)\n\nfig = px.imshow(images, animation_frame=0, binary_string=True, labels=dict(animation_frame=\"scan\"), height=600)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-12T11:09:01.689616Z","iopub.execute_input":"2021-08-12T11:09:01.690219Z","iopub.status.idle":"2021-08-12T11:09:12.692449Z","shell.execute_reply.started":"2021-08-12T11:09:01.690169Z","shell.execute_reply":"2021-08-12T11:09:12.691289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\nimport os\nimport pandas as pd\n\nIDX_list = os.listdir('../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/')\nSEQ_list = ['FLAIR', 'T1w', 'T1wCE', 'T2w']\n\nresult = []\n\nsum = 0\n\nfor idx_elem in IDX_list:\n    for seq_elem in SEQ_list:\n        PATH = f'../input/rsna-miccai-brain-tumor-radiogenomic-classification/train/{idx_elem}/{seq_elem}/'\n        OBJ_list = os.listdir(PATH)\n        for obj_elem in OBJ_list:\n            obj_img = pydicom.dcmread(PATH+obj_elem)\n            position_obj = obj_img.PatientPosition\n            elem_result = [idx_elem, seq_elem, obj_elem, position_obj]\n            result.append(elem_result)\n            if obj_elem != \"HFS\":\n                sum += 1\n            else:\n                pass\n\nprint(\"Non_HFS : \", sum)\n\ncol_name = ['IDX', 'SEQ', 'OBJ', 'POSITION']\nDF_POSITION = pd.DataFrame(result, columns=col_name)\nDF_POSITION.describe()","metadata":{"execution":{"iopub.status.busy":"2021-08-13T05:13:40.669613Z","iopub.execute_input":"2021-08-13T05:13:40.669985Z","iopub.status.idle":"2021-08-13T05:52:22.929931Z","shell.execute_reply.started":"2021-08-13T05:13:40.66995Z","shell.execute_reply":"2021-08-13T05:52:22.928899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport sys \nimport json\nimport glob\nimport random\nimport collections\nimport time\nimport re\n\nimport numpy as np\nimport pandas as pd\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport torch\nfrom torch import nn\nfrom torch.utils import data as torch_data\nfrom sklearn import model_selection as sk_model_selection\nfrom sklearn.linear_model import LogisticRegression as LRModel\nfrom torch.nn import functional as torch_functional\nimport torch.nn.functional as F\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:43.710133Z","iopub.execute_input":"2021-08-25T01:48:43.710656Z","iopub.status.idle":"2021-08-25T01:48:46.797047Z","shell.execute_reply.started":"2021-08-25T01:48:43.710550Z","shell.execute_reply":"2021-08-25T01:48:46.795840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if os.path.exists(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification\"):\n    data_directory = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\n    pytorch3dpath = \"../input/efficientnetpyttorch3d/EfficientNet-PyTorch-3D\"\nelse:\n    data_directory = '/media/roland/data/kaggle/rsna-miccai-brain-tumor-radiogenomic-classification'\n    pytorch3dpath = \"EfficientNet-PyTorch-3D\"\n    \nmri_types = ['FLAIR','T1w','T1wCE','T2w']\nSIZE = 256\nNUM_IMAGES = 64","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:46.798747Z","iopub.execute_input":"2021-08-25T01:48:46.799080Z","iopub.status.idle":"2021-08-25T01:48:46.805411Z","shell.execute_reply.started":"2021-08-25T01:48:46.799045Z","shell.execute_reply":"2021-08-25T01:48:46.804075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sys.path.append(pytorch3dpath)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:47.781029Z","iopub.execute_input":"2021-08-25T01:48:47.781446Z","iopub.status.idle":"2021-08-25T01:48:47.786866Z","shell.execute_reply.started":"2021-08-25T01:48:47.781409Z","shell.execute_reply":"2021-08-25T01:48:47.785591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dicom_image(path, img_size=SIZE, voi_lut=True, rotate=0):\n    dicom = pydicom.read_file(path)\n    data = dicom.pixel_array\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n    if rotate > 0:\n        rot_choices = [0, cv2.ROTATE_90_CLOCKWISE, cv2.ROTATE_90_COUNTERCLOCKWISE, cv2.ROTATE_180]\n        data = cv2.rotate(data, rot_choices[rotate])\n        \n    data = cv2.resize(data, (img_size, img_size))\n    return data","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:50.875866Z","iopub.execute_input":"2021-08-25T01:48:50.876296Z","iopub.status.idle":"2021-08-25T01:48:50.884123Z","shell.execute_reply.started":"2021-08-25T01:48:50.876262Z","shell.execute_reply":"2021-08-25T01:48:50.882707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dicom_images_3d(scan_id, num_imgs=NUM_IMAGES, img_size=SIZE, mri_type=\"FLAIR\", split=\"train\", rotate=0):\n\n    files = sorted(glob.glob(f\"{data_directory}/{split}/{scan_id}/{mri_type}/*.dcm\"), \n               key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])\n\n    middle = len(files)//2\n    num_imgs2 = num_imgs//2\n    p1 = max(0, middle - num_imgs2)\n    p2 = min(len(files), middle + num_imgs2)\n    img3d = np.stack([load_dicom_image(f, rotate=rotate) for f in files[p1:p2]]).T \n    if img3d.shape[-1] < num_imgs:\n        n_zero = np.zeros((img_size, img_size, num_imgs - img3d.shape[-1]))\n        img3d = np.concatenate((img3d,  n_zero), axis = -1)\n        \n    if np.min(img3d) < np.max(img3d):\n        img3d = img3d - np.min(img3d)\n        img3d = img3d / np.max(img3d)\n            \n    return np.expand_dims(img3d,0)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:53.945185Z","iopub.execute_input":"2021-08-25T01:48:53.945651Z","iopub.status.idle":"2021-08-25T01:48:53.957016Z","shell.execute_reply.started":"2021-08-25T01:48:53.945609Z","shell.execute_reply":"2021-08-25T01:48:53.955658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a = load_dicom_images_3d(\"00000\")\nprint(a.shape)\nprint(np.min(a), np.max(a), np.mean(a), np.median(a))","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:55.100168Z","iopub.execute_input":"2021-08-25T01:48:55.100584Z","iopub.status.idle":"2021-08-25T01:48:56.226125Z","shell.execute_reply.started":"2021-08-25T01:48:55.100548Z","shell.execute_reply":"2021-08-25T01:48:56.224740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed):\n    random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:48:59.314875Z","iopub.execute_input":"2021-08-25T01:48:59.315324Z","iopub.status.idle":"2021-08-25T01:48:59.320975Z","shell.execute_reply.started":"2021-08-25T01:48:59.315288Z","shell.execute_reply":"2021-08-25T01:48:59.320102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(12)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:49:00.513958Z","iopub.execute_input":"2021-08-25T01:49:00.514660Z","iopub.status.idle":"2021-08-25T01:49:00.523118Z","shell.execute_reply.started":"2021-08-25T01:49:00.514618Z","shell.execute_reply":"2021-08-25T01:49:00.522149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(f\"{data_directory}/train_labels.csv\")\ndisplay(train_df)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:49:02.057744Z","iopub.execute_input":"2021-08-25T01:49:02.058119Z","iopub.status.idle":"2021-08-25T01:49:02.102483Z","shell.execute_reply.started":"2021-08-25T01:49:02.058086Z","shell.execute_reply":"2021-08-25T01:49:02.101770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train, df_valid = sk_model_selection.train_test_split(\n    train_df, \n    test_size=0.2, \n    random_state=12, \n    stratify=train_df[\"MGMT_value\"],\n)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:49:06.299933Z","iopub.execute_input":"2021-08-25T01:49:06.300351Z","iopub.status.idle":"2021-08-25T01:49:06.314855Z","shell.execute_reply.started":"2021-08-25T01:49:06.300314Z","shell.execute_reply":"2021-08-25T01:49:06.313521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.tail()","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:49:07.833601Z","iopub.execute_input":"2021-08-25T01:49:07.834020Z","iopub.status.idle":"2021-08-25T01:49:07.845273Z","shell.execute_reply.started":"2021-08-25T01:49:07.833984Z","shell.execute_reply":"2021-08-25T01:49:07.844024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset(torch_data.Dataset):\n    def __init__(self, paths, targets=None, mri_type=None, label_smoothing=0.01, split=\"train\", augment=False):\n        self.paths = paths\n        self.targets = targets\n        self.mri_type = mri_type\n        self.label_smoothing = label_smoothing\n        self.split = split\n        self.augment = augment\n          \n    def __len__(self):\n        return len(self.paths)\n    \n    def __getitem__(self, index):\n        scan_id = self.paths[index]\n        if self.targets is None:\n            data = load_dicom_images_3d(str(scan_id).zfill(5), mri_type=self.mri_type[index], split=self.split)\n        else:\n            if self.augment:\n                rotation = np.random.randint(0,4)\n            else:\n                rotation = 0\n\n            data = load_dicom_images_3d(str(scan_id).zfill(5), mri_type=self.mri_type[index], split=\"train\", rotate=rotation)\n\n        if self.targets is None:\n            return {\"X\": torch.tensor(data).float(), \"id\": scan_id}\n        else:\n            y = torch.tensor(abs(self.targets[index]-self.label_smoothing), dtype=torch.float)\n            return {\"X\": torch.tensor(data).float(), \"y\": y}","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:49:11.485994Z","iopub.execute_input":"2021-08-25T01:49:11.486401Z","iopub.status.idle":"2021-08-25T01:49:11.497905Z","shell.execute_reply.started":"2021-08-25T01:49:11.486364Z","shell.execute_reply":"2021-08-25T01:49:11.496936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.net = EfficientNet3D.from_name(\"efficientnet-b0\", override_params={'num_classes': 2}, in_channels=1)\n        n_features = self.net._fc.in_features\n        self.net._fc = nn.Linear(in_features=n_features, out_features=1, bias=True)\n    \n    def forward(self, x):\n        out = self.net(x)\n        return out","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:17:36.107345Z","iopub.execute_input":"2021-08-25T02:17:36.107754Z","iopub.status.idle":"2021-08-25T02:17:36.115337Z","shell.execute_reply.started":"2021-08-25T02:17:36.107718Z","shell.execute_reply":"2021-08-25T02:17:36.114369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Trainer:\n    def __init__(\n        self, \n        model, \n        device, \n        optimizer, \n        criterion\n    ):\n        self.model = model\n        self.device = device\n        self.optimizer = optimizer\n        self.criterion = criterion\n\n        self.best_valid_score = np.inf\n        self.n_patience = 0\n        self.lastmodel = None\n        \n    def fit(self, epochs, train_loader, valid_loader, save_path, patience):        \n        for n_epoch in range(1, epochs + 1):\n            self.info_message(\"EPOCH: {}\", n_epoch)\n            \n            train_loss, train_time = self.train_epoch(train_loader)\n            valid_loss, valid_auc, valid_time = self.valid_epoch(valid_loader)\n            \n            self.info_message(\n                \"[Epoch Train: {}] loss: {:.4f}, time: {:.2f} s            \",\n                n_epoch, train_loss, train_time\n            )\n            \n            self.info_message(\n                \"[Epoch Valid: {}] loss: {:.4f}, auc: {:.4f}, time: {:.2f} s\",\n                n_epoch, valid_loss, valid_auc, valid_time\n            )\n\n            # if True:\n            # if self.best_valid_score < valid_auc: \n            if self.best_valid_score > valid_loss: \n                self.save_model(n_epoch, save_path, valid_loss, valid_auc)\n                self.info_message(\n                     \"auc improved from {:.4f} to {:.4f}. Saved model to '{}'\", \n                    self.best_valid_score, valid_loss, self.lastmodel\n                )\n                self.best_valid_score = valid_loss\n                self.n_patience = 0\n            else:\n                self.n_patience += 1\n            \n            if self.n_patience >= patience:\n                self.info_message(\"\\nValid auc didn't improve last {} epochs.\", patience)\n                break\n            \n    def train_epoch(self, train_loader):\n        self.model.train()\n        t = time.time()\n        sum_loss = 0\n\n        for step, batch in enumerate(train_loader, 1):\n            X = batch[\"X\"].to(self.device)\n            targets = batch[\"y\"].to(self.device)\n            self.optimizer.zero_grad()\n            outputs = self.model(X).squeeze(1)\n            \n            loss = self.criterion(outputs, targets)\n            loss.backward()\n\n            sum_loss += loss.detach().item()\n\n            self.optimizer.step()\n            \n            message = 'Train Step {}/{}, train_loss: {:.4f}'\n            self.info_message(message, step, len(train_loader), sum_loss/step, end=\"\\r\")\n        \n        return sum_loss/len(train_loader), int(time.time() - t)\n    \n    def valid_epoch(self, valid_loader):\n        self.model.eval()\n        t = time.time()\n        sum_loss = 0\n        y_all = []\n        outputs_all = []\n\n        for step, batch in enumerate(valid_loader, 1):\n            with torch.no_grad():\n                X = batch[\"X\"].to(self.device)\n                targets = batch[\"y\"].to(self.device)\n\n                outputs = self.model(X).squeeze(1)\n                loss = self.criterion(outputs, targets)\n\n                sum_loss += loss.detach().item()\n                y_all.extend(batch[\"y\"].tolist())\n                outputs_all.extend(outputs.tolist())\n\n            message = 'Valid Step {}/{}, valid_loss: {:.4f}'\n            self.info_message(message, step, len(valid_loader), sum_loss/step, end=\"\\r\")\n            \n        y_all = [1 if x > 0.5 else 0 for x in y_all]\n        auc = roc_auc_score(y_all, outputs_all)\n        \n        return sum_loss/len(valid_loader), auc, int(time.time() - t)\n    \n    def save_model(self, n_epoch, save_path, loss, auc):\n        self.lastmodel = f\"{save_path}-e{n_epoch}-loss{loss:.3f}-auc{auc:.3f}.pth\"\n        torch.save(\n            {\n                \"model_state_dict\": self.model.state_dict(),\n                \"optimizer_state_dict\": self.optimizer.state_dict(),\n                \"best_valid_score\": self.best_valid_score,\n                \"n_epoch\": n_epoch,\n            },\n            self.lastmodel,\n        )\n    \n    @staticmethod\n    def info_message(message, *args, end=\"\\n\"):\n        print(message.format(*args), end=end)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:17:40.758783Z","iopub.execute_input":"2021-08-25T02:17:40.759314Z","iopub.status.idle":"2021-08-25T02:17:40.789888Z","shell.execute_reply.started":"2021-08-25T02:17:40.759266Z","shell.execute_reply":"2021-08-25T02:17:40.788608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:17:43.124081Z","iopub.execute_input":"2021-08-25T02:17:43.124494Z","iopub.status.idle":"2021-08-25T02:17:43.129305Z","shell.execute_reply.started":"2021-08-25T02:17:43.124433Z","shell.execute_reply":"2021-08-25T02:17:43.128508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_mri_type(df_train, df_valid, mri_type):\n    if mri_type==\"all\":\n        train_list = []\n        valid_list = []\n        for mri_type in mri_types:\n            df_train.loc[:,\"MRI_Type\"] = mri_type\n            train_list.append(df_train.copy())\n            df_valid.loc[:,\"MRI_Type\"] = mri_type\n            valid_list.append(df_valid.copy())\n\n        df_train = pd.concat(train_list)\n        df_valid = pd.concat(valid_list)\n    else:\n        df_train.loc[:,\"MRI_Type\"] = mri_type\n        df_valid.loc[:,\"MRI_Type\"] = mri_type\n\n    print(df_train.shape, df_valid.shape)\n    display(df_train.head())\n    \n    train_data_retriever = Dataset(\n        df_train[\"BraTS21ID\"].values, \n        df_train[\"MGMT_value\"].values, \n        df_train[\"MRI_Type\"].values,\n        augment=True\n    )\n\n    valid_data_retriever = Dataset(\n        df_valid[\"BraTS21ID\"].values, \n        df_valid[\"MGMT_value\"].values,\n        df_valid[\"MRI_Type\"].values\n    )\n\n    train_loader = torch_data.DataLoader(\n        train_data_retriever,\n        batch_size=32,\n        shuffle=True,\n        num_workers=8,\n    )\n\n    valid_loader = torch_data.DataLoader(\n        valid_data_retriever, \n        batch_size=32,\n        shuffle=False,\n        num_workers=8,\n    )\n\n    model = Model()\n    model.to(device)\n\n    #checkpoint = torch.load(\"best-model-all-auc0.555.pth\")\n    #model.load_state_dict(checkpoint[\"model_state_dict\"])\n\n    #print(model)\n\n    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n    #optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n\n    criterion = torch_functional.binary_cross_entropy_with_logits\n\n    trainer = Trainer(\n        model, \n        device, \n        optimizer, \n        criterion\n    )\n\n    history = trainer.fit(\n        10, \n        train_loader, \n        valid_loader, \n        f\"{mri_type}\", \n        10,\n    )\n    \n    return trainer.lastmodel","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:17:44.195182Z","iopub.execute_input":"2021-08-25T02:17:44.195619Z","iopub.status.idle":"2021-08-25T02:17:44.208844Z","shell.execute_reply.started":"2021-08-25T02:17:44.195584Z","shell.execute_reply":"2021-08-25T02:17:44.207210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modelfiles = None","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:17:45.154626Z","iopub.execute_input":"2021-08-25T02:17:45.155019Z","iopub.status.idle":"2021-08-25T02:17:45.159689Z","shell.execute_reply.started":"2021-08-25T02:17:45.154989Z","shell.execute_reply":"2021-08-25T02:17:45.158610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from efficientnet_pytorch_3d import EfficientNet3D","metadata":{"execution":{"iopub.status.busy":"2021-08-25T02:18:42.225434Z","iopub.execute_input":"2021-08-25T02:18:42.225876Z","iopub.status.idle":"2021-08-25T02:18:42.248435Z","shell.execute_reply.started":"2021-08-25T02:18:42.225833Z","shell.execute_reply":"2021-08-25T02:18:42.247250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if not modelfiles:\n    modelfiles = [train_mri_type(df_train, df_valid, m) for m in mri_types]\n    print(modelfiles)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:59:40.435313Z","iopub.execute_input":"2021-08-25T01:59:40.435685Z","iopub.status.idle":"2021-08-25T01:59:40.494936Z","shell.execute_reply.started":"2021-08-25T01:59:40.435656Z","shell.execute_reply":"2021-08-25T01:59:40.493645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport sys \nimport json\nimport glob\nimport random\nimport collections\nimport time\nimport re\n\nimport numpy as np\nimport pandas as pd\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport cv2\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport torch\nfrom torch import nn\nfrom torch.utils import data as torch_data\nfrom sklearn import model_selection as sk_model_selection\nfrom sklearn.linear_model import LogisticRegression as LRModel\nfrom torch.nn import functional as torch_functional\nimport torch.nn.functional as F\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:40:40.543638Z","iopub.execute_input":"2021-08-25T01:40:40.544027Z","iopub.status.idle":"2021-08-25T01:40:43.354945Z","shell.execute_reply.started":"2021-08-25T01:40:40.543946Z","shell.execute_reply":"2021-08-25T01:40:43.353979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if os.path.exists(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification\"):\n    ROOT_DIR = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\nelse:\n    ROOT_DIR = '/media/roland/data/kaggle/rsna-miccai-brain-tumor-radiogenomic-classification'","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:41:56.895190Z","iopub.execute_input":"2021-08-25T01:41:56.895696Z","iopub.status.idle":"2021-08-25T01:41:56.900319Z","shell.execute_reply.started":"2021-08-25T01:41:56.895665Z","shell.execute_reply":"2021-08-25T01:41:56.899653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"raw","source":"mri_types = ['FLAIR','T1w','T1wCE','T2w']\nSIZE = 256\nNUM_IMAGES = 64","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:40:51.418298Z","iopub.execute_input":"2021-08-25T01:40:51.418882Z","iopub.status.idle":"2021-08-25T01:40:51.422835Z","shell.execute_reply.started":"2021-08-25T01:40:51.418834Z","shell.execute_reply":"2021-08-25T01:40:51.421927Z"}}},{"cell_type":"code","source":"def load_dicom_image(path, img_size=SIZE, voi_lut=True, rotate=0):\n    \"\"\"\n    Function: translate from dicom file to array with windowing,\n    rotation, resizing\n\n    Arguments:\n    [0] path,\n    [1] image_size: single number,\n    [2] voi_lut: windowing,\n    [3] optional opencv rotate\n\n    Return: 2D array list (numpy?)\n    \"\"\"\n    dicom = pydicom.read_file(path)\n    data = dicom.pixel_array\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n    if rotate > 0:\n        rot_choices = [0, cv2.ROTATE_90_CLOCKWISE,\n        cv2.ROTATE_90_COUNTERCLOCKWISE,\n        cv2.ROTATE_180]\n        data = cv2.rotate(data, rot_choices[rotate])\n        \n    data = cv2.resize(data, (img_size, img_size))\n    return data","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:41:01.863557Z","iopub.execute_input":"2021-08-25T01:41:01.863905Z","iopub.status.idle":"2021-08-25T01:41:01.871211Z","shell.execute_reply.started":"2021-08-25T01:41:01.863877Z","shell.execute_reply":"2021-08-25T01:41:01.869959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_dicom_images_3d(\n    scan_id,\n    num_imgs=NUM_IMAGES,\n    img_size=SIZE,\n    mri_type=\"FLAIR\",\n    split=\"train\",\n    rotate=0):\n    \"\"\"\n    Function: read the dicom image by scan id, return\n    Arguments:\n    Return:\n    \"\"\"\n    files = sorted(glob.glob(f\"{ROOT_DIR}/{split}/{scan_id}/{mri_type}/*.dcm\"), \n               key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])\n    middle = len(files)//2\n    num_imgs2 = num_imgs//2\n    p1 = max(0, middle - num_imgs2)\n    p2 = min(len(files), middle + num_imgs2)\n    img3d = np.stack([load_dicom_image(f, rotate=rotate) for f in files[p1:p2]]).T \n    if img3d.shape[-1] < num_imgs:\n        n_zero = np.zeros((img_size, img_size, num_imgs - img3d.shape[-1]))\n        img3d = np.concatenate((img3d,  n_zero), axis = -1)\n    if np.min(img3d) < np.max(img3d):\n        img3d = img3d - np.min(img3d)\n        img3d = img3d / np.max(img3d)\n    return np.expand_dims(img3d,0)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:42:25.865391Z","iopub.execute_input":"2021-08-25T01:42:25.866021Z","iopub.status.idle":"2021-08-25T01:42:25.875333Z","shell.execute_reply.started":"2021-08-25T01:42:25.865987Z","shell.execute_reply":"2021-08-25T01:42:25.874591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a = load_dicom_images_3d(\"00000\")\nprint(a.shape)\nprint(np.min(a), np.max(a), np.mean(a), np.median(a))","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:42:40.544543Z","iopub.execute_input":"2021-08-25T01:42:40.544881Z","iopub.status.idle":"2021-08-25T01:42:41.066077Z","shell.execute_reply.started":"2021-08-25T01:42:40.544851Z","shell.execute_reply":"2021-08-25T01:42:41.065137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed):\n    \"\"\"\n    set the seed\n    \"\"\"\n    random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:42:56.433587Z","iopub.execute_input":"2021-08-25T01:42:56.434117Z","iopub.status.idle":"2021-08-25T01:42:56.442556Z","shell.execute_reply.started":"2021-08-25T01:42:56.434066Z","shell.execute_reply":"2021-08-25T01:42:56.441261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(12)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:43:02.124949Z","iopub.execute_input":"2021-08-25T01:43:02.125386Z","iopub.status.idle":"2021-08-25T01:43:02.132719Z","shell.execute_reply.started":"2021-08-25T01:43:02.125350Z","shell.execute_reply":"2021-08-25T01:43:02.131692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(f\"{ROOT_DIR}/train_labels.csv\")\nprint(train_df)","metadata":{"execution":{"iopub.status.busy":"2021-08-25T01:43:19.394457Z","iopub.execute_input":"2021-08-25T01:43:19.394846Z","iopub.status.idle":"2021-08-25T01:43:19.426638Z","shell.execute_reply.started":"2021-08-25T01:43:19.394811Z","shell.execute_reply":"2021-08-25T01:43:19.425578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train, df_valid = sk_model_selection.train_test_split(\n    train_df, \n    test_size=0.2, \n    random_state=12, \n    stratify=train_df[\"MGMT_value\"],\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.tail()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Dataset(torch_data.Dataset):\n    def __init__(self, paths, targets=None, mri_type=None, label_smoothing=0.01, split=\"train\", augment=False):\n        self.paths = paths\n        self.targets = targets\n        self.mri_type = mri_type\n        self.label_smoothing = label_smoothing\n        self.split = split\n        self.augment = augment\n    def __len__(self):\n        return len(self.paths)\n    def __getitem__(self, index):\n        scan_id = self.paths[index]\n        if self.targets is None:\n            data = load_dicom_images_3d(str(scan_id).zfill(5), mri_type=self.mri_type[index], split=self.split)\n        else:\n            if self.augment:\n                rotation = np.random.randint(0,4)\n            else:\n                rotation = 0\n            data = load_dicom_images_3d(str(scan_id).zfill(5), mri_type=self.mri_type[index], split=\"train\", rotate=rotation)\n        if self.targets is None:\n            return {\"X\": torch.tensor(data).float(), \"id\": scan_id}\n        else:\n            y = torch.tensor(abs(self.targets[index]-self.label_smoothing), dtype=torch.float)\n            return {\"X\": torch.tensor(data).float(), \"y\": y}","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.net = EfficientNet3D.from_name(\"efficientnet-b0\", override_params={'num_classes': 2}, in_channels=1)\n        n_features = self.net._fc.in_features\n        self.net._fc = nn.Linear(in_features=n_features, out_features=1, bias=True)\n#         self.conv1 = nn.Conv2d(1, 10, kernel_size=5)\n#         self.conv2 = nn.Conv2d(10, 20, kernel_size=5)\n#         self.conv2_drop = nn.Dropout2d()\n#         self.fc1 = nn.Linear(320, 50)\n#         self.fc2 = nn.Linear(50, 10)\n    def forward(self, x):\n        out = self.net(x)\n        return out\n#         x = F.relu(F.max_pool2d(self.conv1(x), 2))\n#         x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n#         x = x.view(-1, 320)\n#         x = F.relu(self.fc1(x))\n#         x = F.dropout(x, training=self.training)\n#         x = self.fc2(x)\n#         return F.log_softmax(x, dim=1)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Trainer:\n    def __init__(\n        self, \n        model, \n        device, \n        optimizer, \n        criterion\n    ):\n        self.model = model\n        self.device = device\n        self.optimizer = optimizer\n        self.criterion = criterion\n        self.best_valid_score = np.inf\n        self.n_patience = 0\n        self.lastmodel = None\n    def fit(self, epochs, train_loader, valid_loader, save_path, patience):        \n        for n_epoch in range(1, epochs + 1):\n            self.info_message(\"EPOCH: {}\", n_epoch)\n            train_loss, train_time = self.train_epoch(train_loader)\n            valid_loss, valid_auc, valid_time = self.valid_epoch(valid_loader)\n            self.info_message(\n                \"[Epoch Train: {}] loss: {:.4f}, time: {:.2f} s            \",\n                n_epoch, train_loss, train_time\n            )\n            self.info_message(\n                \"[Epoch Valid: {}] loss: {:.4f}, auc: {:.4f}, time: {:.2f} s\",\n                n_epoch, valid_loss, valid_auc, valid_time\n            )\n            # if True:\n            # if self.best_valid_score < valid_auc: \n            if self.best_valid_score > valid_loss: \n                self.save_model(n_epoch, save_path, valid_loss, valid_auc)\n                self.info_message(\n                     \"auc improved from {:.4f} to {:.4f}. Saved model to '{}'\", \n                    self.best_valid_score, valid_loss, self.lastmodel\n                )\n                self.best_valid_score = valid_loss\n                self.n_patience = 0\n            else:\n                self.n_patience += 1\n            if self.n_patience >= patience:\n                self.info_message(\"\\nValid auc didn't improve last {} epochs.\", patience)\n                break\n    def train_epoch(self, train_loader):\n        self.model.train()\n        t = time.time()\n        sum_loss = 0\n        for step, batch in enumerate(train_loader, 1):\n            X = batch[\"X\"].to(self.device)\n            targets = batch[\"y\"].to(self.device)\n            self.optimizer.zero_grad()\n            outputs = self.model(X).squeeze(1)\n            loss = self.criterion(outputs, targets)\n            loss.backward()\n            sum_loss += loss.detach().item()\n            self.optimizer.step()\n            message = 'Train Step {}/{}, train_loss: {:.4f}'\n            self.info_message(message, step, len(train_loader), sum_loss/step, end=\"\\r\")\n        return sum_loss/len(train_loader), int(time.time() - t)\n    def valid_epoch(self, valid_loader):\n        self.model.eval()\n        t = time.time()\n        sum_loss = 0\n        y_all = []\n        outputs_all = []\n        for step, batch in enumerate(valid_loader, 1):\n            with torch.no_grad():\n                X = batch[\"X\"].to(self.device)\n                targets = batch[\"y\"].to(self.device)\n                outputs = self.model(X).squeeze(1)\n                loss = self.criterion(outputs, targets)\n                sum_loss += loss.detach().item()\n                y_all.extend(batch[\"y\"].tolist())\n                outputs_all.extend(outputs.tolist())\n            message = 'Valid Step {}/{}, valid_loss: {:.4f}'\n            self.info_message(message, step, len(valid_loader), sum_loss/step, end=\"\\r\")\n        y_all = [1 if x > 0.5 else 0 for x in y_all]\n        auc = roc_auc_score(y_all, outputs_all)\n        return sum_loss/len(valid_loader), auc, int(time.time() - t)\n    def save_model(self, n_epoch, save_path, loss, auc):\n        self.lastmodel = f\"{save_path}-e{n_epoch}-loss{loss:.3f}-auc{auc:.3f}.pth\"\n        torch.save(\n            {\n                \"model_state_dict\": self.model.state_dict(),\n                \"optimizer_state_dict\": self.optimizer.state_dict(),\n                \"best_valid_score\": self.best_valid_score,\n                \"n_epoch\": n_epoch,\n            },\n            self.lastmodel,\n        )\n    @staticmethod\n    def info_message(message, *args, end=\"\\n\"):\n        print(message.format(*args), end=end)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_mri_type(df_train, df_valid, mri_type):\n    if mri_type==\"all\":\n        train_list = []\n        valid_list = []\n        for mri_type in mri_types:\n            df_train.loc[:,\"MRI_Type\"] = mri_type\n            train_list.append(df_train.copy())\n            df_valid.loc[:,\"MRI_Type\"] = mri_type\n            valid_list.append(df_valid.copy())\n        df_train = pd.concat(train_list)\n        df_valid = pd.concat(valid_list)\n    else:\n        df_train.loc[:,\"MRI_Type\"] = mri_type\n        df_valid.loc[:,\"MRI_Type\"] = mri_type\n    print(df_train.shape, df_valid.shape)\n    print(df_train.head())\n    train_data_retriever = Dataset(\n        df_train[\"BraTS21ID\"].values, \n        df_train[\"MGMT_value\"].values, \n        df_train[\"MRI_Type\"].values,\n        augment=True\n    )\n    valid_data_retriever = Dataset(\n        df_valid[\"BraTS21ID\"].values, \n        df_valid[\"MGMT_value\"].values,\n        df_valid[\"MRI_Type\"].values\n    )\n    train_loader = torch_data.DataLoader(\n        train_data_retriever,\n        batch_size=32,\n        shuffle=True,\n        num_workers=8,\n    )\n    valid_loader = torch_data.DataLoader(\n        valid_data_retriever, \n        batch_size=32,\n        shuffle=False,\n        num_workers=8,\n    )\n    model = Model()\n    model.to(device)\n    #checkpoint = torch.load(\"best-model-all-auc0.555.pth\")\n    #model.load_state_dict(checkpoint[\"model_state_dict\"])\n    #print(model)\n    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n    #optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n    criterion = torch_functional.binary_cross_entropy_with_logits\n    trainer = Trainer(\n        model, \n        device, \n        optimizer, \n        criterion\n    )\n    history = trainer.fit(\n        10, \n        train_loader, \n        valid_loader, \n        f\"{mri_type}\", \n        10,\n    )\n    return trainer.lastmodel","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"modelfiles = None\n# modelfiles = [\"/kaggle/input/efficientnettrainedmodels/FLAIR-e10-loss0.680-auc0.624.pth\",\n#               \"/kaggle/input/efficientnettrainedmodels/T1w-e6-loss0.691-auc0.581.pth\",\n#               \"/kaggle/input/efficientnettrainedmodels/T1wCE-e1-loss0.693-auc0.500.pth\",\n#               \"/kaggle/input/efficientnettrainedmodels/T2w-e3-loss0.694-auc0.570.pth\"]\n\nif not modelfiles:\n    modelfiles = [train_mri_type(df_train, df_valid, m) for m in mri_types]\n    print(modelfiles)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(modelfile, df, mri_type, split):\n    print(\"Predict:\", modelfile, mri_type, df.shape)\n    df.loc[:,\"MRI_Type\"] = mri_type\n    data_retriever = Dataset(\n        df.index.values, \n        mri_type=df[\"MRI_Type\"].values,\n        split=split\n    )\n\n    data_loader = torch_data.DataLoader(\n        data_retriever,\n        batch_size=32,\n        shuffle=False,\n        num_workers=8,\n    )\n   \n    model = Model()\n    model.to(device)\n    \n    checkpoint = torch.load(modelfile)\n    model.load_state_dict(checkpoint[\"model_state_dict\"])\n    model.eval()\n    \n    y_pred = []\n    ids = []\n\n    for e, batch in enumerate(data_loader,1):\n        print(f\"{e}/{len(data_loader)}\", end=\"\\r\")\n        with torch.no_grad():\n            tmp_pred = torch.sigmoid(model(batch[\"X\"].to(device))).cpu().numpy().squeeze()\n            if tmp_pred.size == 1:\n                y_pred.append(tmp_pred)\n            else:\n                y_pred.extend(tmp_pred.tolist())\n            ids.extend(batch[\"id\"].numpy().tolist())\n            \n    preddf = pd.DataFrame({\"BraTS21ID\": ids, \"MGMT_value\": y_pred}) \n    preddf = preddf.set_index(\"BraTS21ID\")\n    return preddf","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = df_train.set_index(\"BraTS21ID\")\n\nfor m, mtype in zip(modelfiles,  mri_types):\n    pred = predict(m, df_train, mtype, \"train\")\n    df_train[mtype] = pred[\"MGMT_value\"]\n\ny = df_train.values[:, 0]\ny = [np.int64(i) for i in y]\ny = np.array(y)\nX = df_train.values[:, 2:6]\n\nemsemble_LR = LRModel(random_state=0).fit(X, y)\n\ndf_valid = df_valid.set_index(\"BraTS21ID\")\nfor m, mtype in zip(modelfiles,  mri_types):\n    pred = predict(m, df_valid, mtype, \"train\")\n    df_valid[mtype] = pred[\"MGMT_value\"]\nX_valid = df_valid.values[:, 2:6]\n\ny_pred = emsemble_LR.predict_proba(X_valid)\ndf_valid[\"MGMT_pred\"] = y_pred[:, 1]\nauc = roc_auc_score(df_valid[\"MGMT_value\"], df_valid[\"MGMT_pred\"])\nprint(f\"Validation ensemble AUC: {auc:.4f}\")\nsns.displot(df_valid[\"MGMT_pred\"])\n\ndf_valid[\"Average\"] = 0\nfor mtype in mri_types:\n    df_valid[\"Average\"] += df_valid[mtype]\ndf_valid[\"Average\"] /= len(modelfiles)\nauc = roc_auc_score(df_valid[\"MGMT_value\"], df_valid[\"Average\"])\nprint(f\"Validation ensemble AUC: {auc:.4f}\")\nsns.displot(df_valid[\"MGMT_pred\"])","metadata":{},"execution_count":null,"outputs":[]}]}