{"cells":[{"metadata":{"trusted":true,"_uuid":"66f1a6a2a44231a6b8e16478d5bd8cc1dddc5398","collapsed":true},"cell_type":"code","source":"%load_ext autoreload\n%autoreload 2","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"markdown","source":"# FastAI exploration\n\nThis kernel will make a small patch to fastai to enable it to read dicom files, and will then use the standard guidelines from the fastai course to explore this dataset."},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"collapsed":true},"cell_type":"code","source":"# Patch dataset.py until my pull request https://github.com/fastai/fastai/pull/777\n# has been incorporated.\nimport fastai\nimport fastai.dataset\nimport pydicom\n\ndef isdicom(fn):\n    '''True if the fn points to a DICOM image'''\n    if fn.endswith('.dcm'):\n        return True\n    # Dicom signature from the dicom spec.\n    with open(fn) as fh:\n        fh.seek(0x80)\n        return fh.read(4)=='DICM'\n\n\ndef open_image(fn):\n    \"\"\" Opens an image using OpenCV given the file path.\n\n    Arguments:\n        fn: the file path of the image\n\n    Returns:\n        The image in RGB format as numpy array of floats normalized to range between 0.0 - 1.0\n    \"\"\"\n    flags = cv2.IMREAD_UNCHANGED+cv2.IMREAD_ANYDEPTH+cv2.IMREAD_ANYCOLOR\n    if not os.path.exists(fn) and not str(fn).startswith(\"http\"):\n        raise OSError('No such file or directory: {}'.format(fn))\n    elif os.path.isdir(fn) and not str(fn).startswith(\"http\"):\n        raise OSError('Is a directory: {}'.format(fn))\n    elif isdicom(fn):\n        slice = pydicom.read_file(fn)\n        if slice.PhotometricInterpretation.startswith('MONOCHROME'):\n            # Make a fake RGB image\n            im = np.stack([slice.pixel_array]*3,-1)\n            return im / ((1 << slice.BitsStored)-1)\n        else:\n            # No support for RGB yet, as it involves various color spaces.\n            # It shouldn't be too difficult to add though, if needed.\n            raise OSError('Unsupported DICOM image with PhotometricInterpretation=={}'.format(slice.PhotometricInterpretation))\n    else:\n        #res = np.array(Image.open(fn), dtype=np.float32)/255\n        #if len(res.shape)==2: res = np.repeat(res[...,None],3,2)\n        #return res\n        try:\n            if str(fn).startswith(\"http\"):\n                req = urllib.urlopen(str(fn))\n                image = np.asarray(bytearray(req.read()), dtype=\"uint8\")\n                im = cv2.imdecode(image, flags).astype(np.float32)/255\n            else:\n                im = cv2.imread(str(fn), flags).astype(np.float32)/255\n            if im is None: raise OSError(f'File not recognized by opencv: {fn}')\n            return cv2.cvtColor(im, cv2.COLOR_BGR2RGB)\n        except Exception as e:\n            raise OSError('Error handling image at: {}'.format(fn)) from e\n\nfastai.dataset.isdicom=isdicom\nfastai.dataset.pydicom=pydicom\nfastai.dataset.open_image=open_image\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"57d3ff2a69a689d9b671098e23e0e06db994833f"},"cell_type":"markdown","source":"# Setup\n\nWith the dicom reader in place, the normal flow of fitting from fastai should work. We choose a modest file size, and just do a few epochs of fitting."},{"metadata":{"trusted":true,"_uuid":"8465f7c4c4ee2e7e408601ac7a30944ad5daa645","collapsed":true},"cell_type":"code","source":"from fastai.conv_learner import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"48958e9de074340f854f61244f83243715125d0d"},"cell_type":"code","source":"# Rewrite the train csv file to contain only two columns as expected by fastai\nlabel_csv = '../input/rsna-pneumonia-detection-challenge/stage_1_train_labels.csv'\ndf = pd.read_csv(label_csv)\ndf[['patientId','Target']].to_csv('train_target_labels.csv',index=False)\nlabel_csv = 'train_target_labels.csv'\ndf = pd.read_csv(label_csv)\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4a9e6029f79d8691e1536fb26870c361f750bda6"},"cell_type":"code","source":"PATH = '../input/rsna-pneumonia-detection-challenge'\nTMP_PATH = \"/tmp/tmp\"\nMODEL_PATH = \"/tmp/model/\"\nsz = 224\narch = resnet34\nbs = 64\n\nn = len(df)\nval_idxs = get_cv_idxs(n) # random 20% data for validation set\n\naug_tfms=transforms_side_on # Use None for faster testing\ntfms = tfms_from_model(arch, sz, aug_tfms=aug_tfms, max_zoom=1.1)\ndata = ImageClassifierData.from_csv(PATH, 'stage_1_train_images', label_csv, test_name='stage_1_test_images', \n                                    val_idxs=val_idxs, \n                                    suffix='.dcm', \n                                    tfms=tfms,  # just for fast testing\n                                    bs=bs)\nlearn = ConvLearner.pretrained(arch, data, tmp_name=TMP_PATH, models_name=MODEL_PATH)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5e16646d443bd811a1408e9391baff73002d13e4"},"cell_type":"markdown","source":"# Fitting\nJust run a few epochs of fitting"},{"metadata":{"trusted":true,"_uuid":"eef896e9d7d816cce3aea5b3bb82d8ce16bb7376"},"cell_type":"code","source":"learn.fit(0.02,3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4aed369b961d255950d000400540d8d5dccaabbe","collapsed":true},"cell_type":"markdown","source":"# Conclusion\nWith this setup in place, it should be straight-forward to apply further advanced concepts from the course, e.g. heatmaps."},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"82d17c03f13d2e5ec92c845f377992b5365a154b"},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}