{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Introduction\n\nIt is a fun competition, but I have tied up with things therefore didn't get much time to play this competition. \n\nMy take away from this competition is the EDA and pre-processing. After going over Jermey's kernel and few Radiologist windowing, I am gonna share how to do this with V1. \n\nThe main reason is fastai_v2 is still under developing and changing everyday, also, few people like me didn't get much time to study v2 but spent most of time on v1 can still play with it.\n\nThis kernel used some codes from the following kernels:\n\n1. https://www.kaggle.com/jhoward/don-t-see-like-a-radiologist-fastai\n\n2. https://www.kaggle.com/akensert/inceptionv3-prev-resnet50-keras-baseline-model\n\n3. https://github.com/radekosmulski/rsna-intracranial\n\nHere is a brief overview:\n\n1. Use Radek's way to create train.csv file for feeding into fastai datablock API\n2. Use the standard radiologist windowing (you can also adpot this from Jeremy's windowing, but I still didn't figure out a proper way to do the normalization)\n3. Use Radek's monkey patch method to handle NAN\n\n\n\n"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom fastai.vision import *\nfrom fastai import *\nfrom fastai.data_block import _maybe_squeeze\n\nimport pydicom\nimport os\nimport matplotlib.pyplot as plt\n\n\nfrom math import ceil, floor, log\nimport cv2","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"path = Path('../input/rsna-intracranial-hemorrhage-detection/')\npath_trn = path/'stage_1_train_images'\npath_tst = path/'stage_1_test_images'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path_df = Path('../input/fastai-meta')\ndf_train = pd.read_csv(path_df/'train_fastai_format.csv')\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Radek's starter pack has .png as suffix, let's build an end to end solution without saving the dcm files to png"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train['fn'] = df_train['fn'].apply(lambda x: x.split('.')[0] + '.dcm' )\ndf_train.to_csv('/kaggle/working/train.csv',index=False)\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Pre-processing / Windowing\n\nUsed Jeremy's kernel to fix pixels\n\nUsed Akensert's kernel for radiologist windowing\n\nFinally, override the fastai_v1 vision package open method, this way, it will open image base on our windowing\ninstead of raw HU values"},{"metadata":{"_cell_guid":"","_uuid":"","trusted":true},"cell_type":"code","source":"'''\nYou can also change the window to any other form, for simplicity, I will just use the standard radiologist's windowing\n\n1. https://www.kaggle.com/jhoward/don-t-see-like-a-radiologist-fastai\n\n2. https://www.kaggle.com/akensert/inceptionv3-prev-resnet50-keras-baseline-model\n\n'''\n\ndef correct_dcm(dcm):\n    x = dcm.pixel_array + 1000\n    px_mode = 4096\n    x[x>=px_mode] = x[x>=px_mode] - px_mode\n    dcm.PixelData = x.tobytes()\n    dcm.RescaleIntercept = -1000\n\ndef window_image(dcm, window_center, window_width):\n    \n    if (dcm.BitsStored == 12) and (dcm.PixelRepresentation == 0) and (int(dcm.RescaleIntercept) > -100):\n        correct_dcm(dcm)\n    \n    img = dcm.pixel_array * dcm.RescaleSlope + dcm.RescaleIntercept\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    img = np.clip(img, img_min, img_max)\n\n    return img\n\ndef bsb_window(dcm):\n    brain_img = window_image(dcm, 40, 80)\n    subdural_img = window_image(dcm, 80, 200)\n    soft_img = window_image(dcm, 40, 380)\n    \n    brain_img = (brain_img - 0) / 80\n    subdural_img = (subdural_img - (-20)) / 200\n    soft_img = (soft_img - (-150)) / 380\n    bsb_img = np.array([brain_img, subdural_img, soft_img]).transpose(1,2,0)\n\n    return bsb_img\n\n\ndef _load_format(path, convert_mode, after_open)->Image:\n    dcm = pydicom.dcmread(path)\n    try:\n        img = bsb_window(dcm)\n    except:\n        img = np.zeros((512,512,3))\n    \n    return Image(pil2tensor(img, np.float32))\n\nvision.data.open_image = _load_format\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Radek's monkey patch to work out NAN in pandas\ndef modified_label_from_df(self, cols:IntsOrStrs=1, label_cls:Callable=None, **kwargs):\n    \"Label `self.items` from the values in `cols` in `self.inner_df`.\"\n    self.inner_df.labels.fillna('', inplace=True)\n    labels = self.inner_df.iloc[:,df_names_to_idx(cols, self.inner_df)]\n    assert labels.isna().sum().sum() == 0, f\"You have NaN values in column(s) {cols} of your dataframe, please fix it.\"\n    if is_listy(cols) and len(cols) > 1 and (label_cls is None or label_cls == MultiCategoryList):\n        new_kwargs,label_cls = dict(one_hot=True, classes= cols),MultiCategoryList\n        kwargs = {**new_kwargs, **kwargs}\n    return self._label_from_list(_maybe_squeeze(labels), label_cls=label_cls, **kwargs)\n\nItemList.label_from_df = modified_label_from_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"# Make sure it is working with fastai_v1"},{"metadata":{"trusted":true},"cell_type":"code","source":"img = _load_format(str(path_trn) + '/ID_5c8b5d701.dcm',None,None)\ntype(img),img.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"markdown","source":"# Back to standard Fastai_v1\n\n1. Override vision.open\n2. Override label_from_df\n\nNow we are ready to build fastai_v1 datablock API"},{"metadata":{"trusted":true},"cell_type":"code","source":"path = Path('../input')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Some data-argumentation I found useful for my baseline model"},{"metadata":{"trusted":true},"cell_type":"code","source":"tfms = get_transforms(flip_vert=True,  max_warp=0., max_rotate=60., max_zoom=1.15)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = (ImageList\n        .from_csv(path,'/kaggle/working/train.csv',folder='rsna-intracranial-hemorrhage-detection/stage_1_train_images')\n        .split_by_rand_pct(seed=42)\n        .label_from_df(label_delim=' ')\n        .transform(tfms,size=(128,128))\n        .databunch(bs=64,num_workers=2)\n        .normalize(imagenet_stats)\n       )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Let's check"},{"metadata":{"trusted":true},"cell_type":"code","source":"data.show_batch(rows=3,figsize=(12,8))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn = cnn_learner(data,models.resnet18,model_dir='/kaggle/working',metrics=[accuracy_thresh]).to_fp16()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Hope this helps few people play this competition with fastai v1.\n\nEspecially if stage-2 doesn't allow you to pre-process and save the files to make prediction. Probably need an end to end way to handle test set."},{"metadata":{},"cell_type":"markdown","source":"Speical thanks to DrHB :)"},{"metadata":{"trusted":true},"cell_type":"code","source":"# learn.lr_find()\n# learn.recorder.plot(suggestion=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# from fastai.callbacks import SaveModelCallback\n# lr = 1e-2\n# learn.fit_one_cycle(1,slice(lr))\n# learn.fit_one_cycle(4,slice(lr),callbacks=[SaveModelCallback(learn,every='epoch',name='res18-128')])","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":1}