{"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":"# SIIM-FISABIO-RSNA COVID-19 Detection\n\n## Introduction \n\nFive times more deadly than the flu, COVID-19 causes significant morbidity and mortality. Like other pneumonias, pulmonary infection with COVID-19 results in inflammation and fluid in the lungs. COVID-19 looks very similar to other viral and bacterial pneumonias on chest radiographs, which makes it difficult to diagnose. Your computer vision model to detect and localize COVID-19 would help doctors provide a quick and confident diagnosis. As a result, patients could get the right treatment before the most severe effects of the virus take hold.\n\n![chest](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F603584%2Fd514aaf604bc9667b518b232a77d1aa7%2FCXR%20image1.jpg?generation=1620769201081719&alt=media)\n\nCurrently, COVID-19 can be diagnosed via polymerase chain reaction to detect genetic material from the virus or chest radiograph. However, it can take a few hours and sometimes days before the molecular test results are back. By contrast, chest radiographs can be obtained in minutes. While guidelines exist to help radiologists differentiate COVID-19 from other types of infection, their assessments vary. In addition, non-radiologists could be supported with better localization of the disease, such as with a visual bounding box.\n\nAs the leading healthcare organization in their field, the Society for Imaging Informatics in Medicine (SIIM)'s mission is to advance medical imaging informatics through education, research, and innovation. SIIM has partnered with the Foundation for the Promotion of Health and Biomedical Research of Valencia Region (FISABIO), Medical Imaging Databank of the Valencia Region (BIMCV) and the Radiological Society of North America (RSNA) for this competition.\n\nIn this competition, you’ll identify and localize COVID-19 abnormalities on chest radiographs. In particular, you'll categorize the radiographs as negative for pneumonia or typical, indeterminate, or atypical for COVID-19. You and your model will work with imaging data and annotations from a group of radiologists.\n\nIf successful, you'll help radiologists diagnose the millions of COVID-19 patients more confidently and quickly. This will also enable doctors to see the extent of the disease and help them make decisions regarding treatment. Depending upon severity, affected patients may need hospitalization, admission into an intensive care unit, or supportive therapies like mechanical ventilation. As a result of better diagnosis, more patients will quickly receive the best care for their condition, which could mitigate the most severe effects of the virus.\n\n","metadata":{}},{"cell_type":"markdown","source":"## Dev idea \n\n- Convert .dcm files to .png \n- ","metadata":{}},{"cell_type":"markdown","source":"### Pydicom env packages","metadata":{}},{"cell_type":"code","source":"!conda install '/kaggle/input/pydicom-conda-helper/libjpeg-turbo-2.1.0-h7f98852_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/gdcm-2.8.9-py37h500ead1_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/conda-4.10.1-py37h89c1867_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/certifi-2020.12.5-py37h89c1867_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/openssl-1.1.1k-h7f98852_0.tar.bz2' -c conda-forge -y","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:04:17.472955Z","iopub.execute_input":"2021-06-02T12:04:17.473270Z","iopub.status.idle":"2021-06-02T12:04:55.775580Z","shell.execute_reply.started":"2021-06-02T12:04:17.473242Z","shell.execute_reply":"2021-06-02T12:04:55.774399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\nfrom PIL import Image\nimport pandas as pd\nfrom tqdm.auto import tqdm","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:04:55.778449Z","iopub.execute_input":"2021-06-02T12:04:55.778785Z","iopub.status.idle":"2021-06-02T12:04:55.785466Z","shell.execute_reply.started":"2021-06-02T12:04:55.778750Z","shell.execute_reply":"2021-06-02T12:04:55.784383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### DCM TO PNG","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\n\ndef read_xray(path, voi_lut = True, fix_monochrome = True):\n    dicom = pydicom.read_file(path)\n    \n    # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to \n    # \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n               \n    # depending on this value, X-ray may look inverted - fix that:\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n        \n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n        \n    return data","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:04:55.787025Z","iopub.execute_input":"2021-06-02T12:04:55.787326Z","iopub.status.idle":"2021-06-02T12:04:55.798329Z","shell.execute_reply.started":"2021-06-02T12:04:55.787287Z","shell.execute_reply":"2021-06-02T12:04:55.797110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Processing and resizing of the image","metadata":{}},{"cell_type":"code","source":"def resize(array, size, keep_ratio=False, resample=Image.LANCZOS):\n    im = Image.fromarray(array)\n    \n    if keep_ratio:\n        im.thumbnail((size, size), resample)\n    else:\n        im = im.resize((size, size), resample)\n    \n    return im","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:04:55.799894Z","iopub.execute_input":"2021-06-02T12:04:55.800304Z","iopub.status.idle":"2021-06-02T12:04:55.813094Z","shell.execute_reply.started":"2021-06-02T12:04:55.800252Z","shell.execute_reply":"2021-06-02T12:04:55.811935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Call in the two driver functions to convert","metadata":{}},{"cell_type":"code","source":"split = 'test'\nsave_dir = f'/kaggle/tmp/{split}/'\n\nos.makedirs(save_dir, exist_ok=True)\n\nsave_dir = f'/kaggle/tmp/{split}/study/'\nos.makedirs(save_dir, exist_ok=True)\n\nfor dirname, _, filenames in tqdm(os.walk(f'../input/siim-covid19-detection/{split}')):\n    for file in filenames:\n        # set keep_ratio=True to have original aspect ratio\n        xray = read_xray(os.path.join(dirname, file))\n        im = resize(xray, size=1000)  \n        study = dirname.split('/')[-2] + '_study.png'\n        im.save(os.path.join(save_dir, study))","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:04:55.814508Z","iopub.execute_input":"2021-06-02T12:04:55.814823Z","iopub.status.idle":"2021-06-02T12:19:08.553899Z","shell.execute_reply.started":"2021-06-02T12:04:55.814785Z","shell.execute_reply":"2021-06-02T12:19:08.552902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Predict flow \n\n- read in sample \n- train on keras model \n[source](https://www.kaggle.com/h053473666/siim-covid19-efnb7-train-study)\n","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\n\ndf = pd.read_csv('../input/siim-covid19-detection/sample_submission.csv')\nid_laststr_list  = []\nfor i in range(df.shape[0]):\n    id_laststr_list.append(df.loc[i,'id'][-1])\ndf['id_last_str'] = id_laststr_list\n\nstudy_len = df[df['id_last_str'] == 'y'].shape[0]","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:19:08.555455Z","iopub.execute_input":"2021-06-02T12:19:08.555771Z","iopub.status.idle":"2021-06-02T12:19:08.602066Z","shell.execute_reply.started":"2021-06-02T12:19:08.555742Z","shell.execute_reply":"2021-06-02T12:19:08.601210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/kerasapplications -q\n!pip install /kaggle/input/efficientnet-keras-source-code/ -q --no-deps\n\nimport os\n\nimport efficientnet.tfkeras as efn\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\n\ndef auto_select_accelerator():\n    try:\n        tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n        tf.config.experimental_connect_to_cluster(tpu)\n        tf.tpu.experimental.initialize_tpu_system(tpu)\n        strategy = tf.distribute.experimental.TPUStrategy(tpu)\n        print(\"Running on TPU:\", tpu.master())\n    except ValueError:\n        strategy = tf.distribute.get_strategy()\n    print(f\"Running on {strategy.num_replicas_in_sync} replicas\")\n\n    return strategy\n\n\ndef build_decoder(with_labels=True, target_size=(400, 400), ext='jpg'):\n    def decode(path):\n        file_bytes = tf.io.read_file(path)\n        if ext == 'png':\n            img = tf.image.decode_png(file_bytes, channels=3)\n        elif ext in ['jpg', 'jpeg']:\n            img = tf.image.decode_jpeg(file_bytes, channels=3)\n        else:\n            raise ValueError(\"Image extension not supported\")\n\n        img = tf.cast(img, tf.float32) / 355.0\n        img = tf.image.resize(img, target_size)\n\n        return img\n\n    def decode_with_labels(path, label):\n        return decode(path), label\n\n    return decode_with_labels if with_labels else decode\n\n\ndef build_augmenter(with_labels=True):\n    def augment(img):\n        img = tf.image.random_flip_left_right(img)\n        img = tf.image.random_flip_up_down(img)\n        return img\n\n    def augment_with_labels(img, label):\n        return augment(img), label\n\n    return augment_with_labels if with_labels else augment\n\n\ndef build_dataset(paths, labels=None, bsize=40, cache=True,\n                  decode_fn=None, augment_fn=None,\n                  augment=True, repeat=True, shuffle=1024, \n                  cache_dir=\"\"):\n    if cache_dir != \"\" and cache is True:\n        os.makedirs(cache_dir, exist_ok=True)\n\n    if decode_fn is None:\n        decode_fn = build_decoder(labels is not None)\n\n    if augment_fn is None:\n        augment_fn = build_augmenter(labels is not None)\n\n    AUTO = tf.data.experimental.AUTOTUNE\n    slices = paths if labels is None else (paths, labels)\n\n    dset = tf.data.Dataset.from_tensor_slices(slices)\n    dset = dset.map(decode_fn, num_parallel_calls=AUTO)\n    dset = dset.cache(cache_dir) if cache else dset\n    dset = dset.map(augment_fn, num_parallel_calls=AUTO) if augment else dset\n    dset = dset.repeat() if repeat else dset\n    dset = dset.shuffle(shuffle) if shuffle else dset\n    dset = dset.batch(bsize).prefetch(AUTO)\n\n    return dset\n\n#COMPETITION_NAME = \"siim-cov19-test-img512-study-600\"\nstrategy = auto_select_accelerator()\nBATCH_SIZE = strategy.num_replicas_in_sync * 20\n\nIMSIZE = (224, 240, 260, 300, 380, 456, 528, 600)\n\n#load_dir = f\"/kaggle/input/{COMPETITION_NAME}/\"\nsub_df = pd.read_csv('../input/siim-covid19-detection/sample_submission.csv')\nsub_df = sub_df[:study_len]\ntest_paths = f'/kaggle/tmp/{split}/study/' + sub_df['id'] +'.png'\n\nsub_df['negative'] = 0\nsub_df['typical'] = 0\nsub_df['indeterminate'] = 0\nsub_df['atypical'] = 0\n\n\nlabel_cols = sub_df.columns[2:]\n\ntest_decoder = build_decoder(with_labels=False, target_size=(IMSIZE[7], IMSIZE[7]), ext='png')\ndtest = build_dataset(\n    test_paths, bsize=BATCH_SIZE, repeat=False, \n    shuffle=False, augment=False, cache=False,\n    decode_fn=test_decoder\n)\n\nwith strategy.scope():\n    \n    models = []\n    \n    models0 = tf.keras.models.load_model(\n        '../input/siim-covid19-efnb7-train-study/model0.h5'\n    )\n    models1 = tf.keras.models.load_model(\n        '../input/siim-covid19-efnb7-train-study/model1.h5'\n    )\n    models2 = tf.keras.models.load_model(\n        '../input/siim-covid19-efnb7-train-study/model2.h5'\n    )\n    models3 = tf.keras.models.load_model(\n        '../input/siim-covid19-efnb7-train-study/model3.h5'\n    )\n    models4 = tf.keras.models.load_model(\n        '../input/siim-covid19-efnb7-train-study/model4.h5'\n    )\n    \n    models.append(models0)\n    models.append(models1)\n    models.append(models2)\n    models.append(models3)\n    models.append(models4)\n\n    \n    \n    \nsub_df[label_cols] = sum([model.predict(dtest, verbose=1) for model in models]) / len(models)","metadata":{"execution":{"iopub.status.busy":"2021-06-02T12:19:08.603730Z","iopub.execute_input":"2021-06-02T12:19:08.604093Z","iopub.status.idle":"2021-06-02T16:24:47.316301Z","shell.execute_reply.started":"2021-06-02T12:19:08.604052Z","shell.execute_reply":"2021-06-02T16:24:47.314695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.columns = ['id', 'PredictionString1', 'negative', 'typical', 'indeterminate', 'atypical']\ndf = pd.merge(df, sub_df, on = 'id', how = 'left')","metadata":{"execution":{"iopub.status.busy":"2021-06-02T16:24:47.322477Z","iopub.execute_input":"2021-06-02T16:24:47.322841Z","iopub.status.idle":"2021-06-02T16:24:47.357749Z","shell.execute_reply.started":"2021-06-02T16:24:47.322766Z","shell.execute_reply":"2021-06-02T16:24:47.356801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in range(study_len):\n    negative = df.loc[i,'negative']\n    typical = df.loc[i,'typical']\n    indeterminate = df.loc[i,'indeterminate']\n    atypical = df.loc[i,'atypical']\n    df.loc[i, 'PredictionString'] = f'negative {negative} 0 0 1 1 typical {typical} 0 0 1 1 indeterminate {indeterminate} 0 0 1 1 atypical {atypical} 0 0 1 1'","metadata":{"execution":{"iopub.status.busy":"2021-06-02T16:24:47.359159Z","iopub.execute_input":"2021-06-02T16:24:47.359457Z","iopub.status.idle":"2021-06-02T16:24:47.890634Z","shell.execute_reply.started":"2021-06-02T16:24:47.359428Z","shell.execute_reply":"2021-06-02T16:24:47.889693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Save into csv to submit","metadata":{}},{"cell_type":"code","source":"final = df[['id', 'PredictionString']]\n\nfinal.to_csv('./submission.csv',index=False)\nfinal.head(10)","metadata":{"execution":{"iopub.status.busy":"2021-06-02T16:24:47.891902Z","iopub.execute_input":"2021-06-02T16:24:47.892172Z","iopub.status.idle":"2021-06-02T16:24:47.951169Z","shell.execute_reply.started":"2021-06-02T16:24:47.892145Z","shell.execute_reply":"2021-06-02T16:24:47.950558Z"},"trusted":true},"execution_count":null,"outputs":[]}]}