{"cells":[{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"from sklearn.utils import shuffle\nfrom IPython.core.display import display, HTML, Javascript\nfrom string import Template\nimport json, random\nimport IPython.display\nfrom plotly.offline import init_notebook_mode, iplot\nfrom plotly import subplots\nimport plotly.figure_factory as ff\nimport plotly as py\nimport plotly.graph_objects as go\ninit_notebook_mode(connected=True)\n\n\n# Defining all our palette colors\nprimary_blue = \"#496595\"\nprimary_blue2 = \"#85a1c1\"\nprimary_blue3 = \"#3f4d63\"\nprimary_grey = \"#c6ccd8\"\nprimary_black = \"#202022\"\nprimary_bgcolor = \"#f4f0ea\"\n\n# \"coffee\" pallette turqoise-gold.\nf1 = \"#a2885e\"\nf2 = \"#e9cf87\"\nf3 = \"#f1efd9\"\nf4 = \"#8eb3aa\"\nf5 = \"#235f83\"\nf6 = \"#b4cde3\"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"html_contents =\"\"\"\n<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n    <style>\n    .toc h2{\n        color: white;\n        background: #3f4d63;\n        font-weight: 600;\n        font-family: Helvetica;\n        font-size: 23px;\n        padding: 6px 12px;\n        margin-bottom: 2px;\n    }\n    \n    .toc ol li{\n        list-style:none;\n        line-height:normal;\n        }\n     \n    .toc li{\n        background: #235f83;\n        color: white;\n        font-weight: 600;\n        font-family: Helvetica;\n        font-size: 18px;\n        margin-bottom: 2px;\n        padding: 6px 12px;\n    }\n\n    .toc ol ol li{\n        background: #fff;\n        color: #4d4d4d;\n        font-weight: 400;\n        font-size: 15px;\n        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n        margin-top: 0px;\n        margin-bottom: 0px;\n        padding: 3px 12px;\n    } \n    \n    .section_title{\n        background-color: #3f4d63;\n        color: white;\n        font-family: Helvetica;\n        font-size: 25px;\n        padding: 6px 12px;\n        margin-bottom: 5px;\n    }\n    .subsection_title{\n        background: #235f83;\n        color: white;\n        font-family: Helvetica;\n        font-size: 21px;\n        padding: 6px 12px;\n        margin-bottom: 0px;\n    }\n    .sidenote{\n        font-size: 13px;\n        border: 1px solid #d7d7d7;\n        padding: 1px 10px 2px;\n        box-shadow: 1px 1px 2px 1px rgba(0,0,0,0.3);\n        margin-bottom: 3px;\n    }\n    </style>\n    </head>\n    <body>\n        <div class=\"toc\">\n        \n        <ol> \n        <h2> Table of Contents </h2>\n        <li>1. Introduction </li> \n        <li>2. Basic Data Exploration</li>\n        <li>3. Utility functions</li>\n        <li>4. Image and Masks Visualizations</li>\n        <ol> \n            <li>4.1 Train Images </li>\n            <li>4.2 Train Images and Masks </li> \n            <li>4.3 Test Images </li> \n            <li>4.4 Plot Image and Mask </li> \n            <li>4.5 Plot Sliced Image and Mask </li> \n            <li>4.6 Plot Grid Image with Mask </li> \n        </ol>\n        <li>5. Metadata Analysis</li>\n        <li>6. References </li>\n        </ol>\n        </div>\n    </body>\n</html>\n\"\"\"\n\nHTML(html_contents)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 1. Introduction\n\nThe Human BioMolecular Atlas Program (HuBMAP) is working to catalyze to catalyze the development of a framework for mapping of human body at the level of glomeruli functional tissue units(FTUs). HuBMAP aims to be an open map of the human body at the celular level. \n\nIn this challenge, we will detect the FTUs across different tissue preparation pipelines. An FTU is a three dimensional block of cells centered around a capillary, such that each cell in this block is within diffusion distance from any other cell in the same block (de Bono, 2013).\n\nThe HuBMAP data used in this competition includes 11 frozen and 9 Formalin fixed Paraffin Embedded (FFPE) PAS kidney images.Glomeruli FTU annotations exist for all 20 tissue samples."},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"!pip install -q -U pip\n!pip install -q -U seaborn\n\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport cv2\nimport tifffile\nfrom PIL import Image\nimport cv2\nimport os\nfrom tqdm.notebook import tqdm\nimport zipfile","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2. Basic Data Exploration"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"BASE_PATH = \"../input/hubmap-kidney-segmentation/\"\nTRAIN_PATH = os.path.join(BASE_PATH, \"train\")\n\nprint(os.listdir(BASE_PATH))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sz = 256       # Size of the tiles\nreduce = 4     # Reduce the original images by 4 times\nMASKS = '../input/hubmap-kidney-segmentation/train.csv'\nDATA = '../input/hubmap-kidney-segmentation/train/'\nOUT_TRAIN = 'train.zip'\nOUT_MASKS = 'masks.zip'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Train masks**\n\ntrain.csv contains the unique IDs of each image, as well as RLE-encoded representation of the mask for the objects of the image."},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(os.path.join(BASE_PATH, \"train.csv\"))\ndf_train","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Submission df**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"df_sub = pd.read_csv(os.path.join(BASE_PATH, \"sample_submission.csv\"))\ndf_sub","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Number of Samples**"},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"print(f\"Number of train images: {df_train.shape[0]}\")\nprint(f\"Number of test images: {df_sub.shape[0]}\")\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Train and test metadata**\n\nHuBMAP-20-dataset_information.csv contains additional information including anonymized patient data about each image"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_info = pd.read_csv(os.path.join(BASE_PATH, \"HuBMAP-20-dataset_information.csv\"))\ndf_info.sample(5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 3. Utility functions"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"def rle2mask(mask_rle, shape):\n    \"\"\"\n    mask_rle : run-length as string formated (start length)\n    shape: (width, height) of array to return\n    Returns numpy array, 1- mask, 0-background\n    \"\"\"\n    \n    s= mask_rle.split()\n    starts, lengths = [\n        np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])\n    ]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0] * shape[1], dtype = np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo : hi] = 1\n    return img.reshape(shape).T\n\ndef read_image(image_id, scale=None, verbose=1):\n    image = tifffile.imread(\n        os.path.join(BASE_PATH, f\"train/{image_id}.tiff\")\n    )\n    if len(image.shape) == 5:\n        image = image.squeeze().transpose(1, 2, 0)\n    \n    mask = rle2mask(\n        df_train[df_train[\"id\"] == image_id][\"encoding\"].values[0], \n        (image.shape[1], image.shape[0])\n    )\n    \n    if verbose:\n        print(f\"[{image_id}] Image shape: {image.shape}\")\n        print(f\"[{image_id}] Mask shape: {mask.shape}\")\n    \n    if scale:\n        new_size = (image.shape[1] // scale, image.shape[0] // scale)\n        image = cv2.resize(image, new_size)\n        mask = cv2.resize(mask, new_size)\n        \n        if verbose:\n            print(f\"[{image_id}] Resized Image shape: {image.shape}\")\n            print(f\"[{image_id}] Resized Mask shape: {mask.shape}\")\n        \n    return image, mask\n\ndef read_test_image(image_id, scale=None, verbose = 1):\n    image = tifffile.imread(\n    os.path.join(BASE_PATH, f\"test/{image_id}.tiff\")\n    )\n    if len(image.shape) == 5:\n        image = image.squeeze().transpose(1,2,0)\n        \n    if verbose:\n        print(f\"[{image_id}] Image shape: {image.shape}\")\n        \n    if scale:\n        new_size = (image.shape[1] // scale, image.shape[0]//scale)\n        image = cv2.resize(image, new_size)\n        \n    if verbose:\n        print(f\"[{image_id}] Resize Image shape: {image.shape}\")\n        \n    return image\n\ndef plot_image_and_mask(image, mask, image_id):\n    plt.figure(figsize=(16, 10))\n    \n    plt.subplot(1, 3, 1)\n    plt.imshow(image)\n    plt.title(f\"Image {image_id}\", fontsize=18)\n    \n    plt.subplot(1, 3, 2)\n    plt.imshow(image)\n    plt.imshow(mask, cmap = \"hot\", alpha = 0.5)\n    plt.title(f\"Image {image_id} + mask\", fontsize=18)\n    \n    plt.subplot(1,3,3)\n    plt.imshow(mask, cmap = \"hot\")\n    plt.title(f\"Mask\", fontsize = 18)\n    plt.show()\n    \n\ndef plot_grid_image_with_mask(image, mask):\n    plt.figure(figsize=(16,16))\n    \n    w_len = image.shape[0]\n    h_len = image.shape[1]\n    \n    min_len = min(w_len, h_len)\n    w_start = (w_len - min_len) // 2\n    h_start = (h_len - min_len) // 2\n    \n    plt.imshow(image[w_start : w_start + min_len, h_start : h_start + min_len])\n    plt.imshow(mask[w_start : w_start + min_len, h_start : h_start + min_len], cmap=\"hot\", alpha = 0.5,)\n    plt.axis(\"off\")\n    plt.show()\n    \n\ndef plot_slice_image_and_mask(image, mask, start_h, end_h, start_w, end_w):\n    plt.figure(figsize=(16,5))\n    sub_image = image[start_h:end_h, start_w:end_w, :]\n    sub_mask = mask[start_h:end_h, start_w:end_w]\n    \n    plt.subplot(1,3,1)\n    plt.imshow(sub_image)\n    plt.axis(\"off\")\n    \n    plt.subplot(1,3,2)\n    plt.imshow(sub_image)\n    plt.imshow(sub_mask, cmap=\"hot\", alpha = 0.5)\n    plt.axis(\"off\")\n    \n    plt.subplot(1,3,3)\n    plt.imshow(sub_mask, cmap=\"hot\")\n    plt.axis(\"off\")\n    \n    plt.show()\n    \ndef enc2mask(encs, shape):\n    img = np.zeros(shape[0]*shape[1], dtype=np.int8)\n    for m, enc in enumerate(encs):\n        if isinstance(enc,np.float) and np.isnan(enc): continue\n        s = enc.split()\n        for i in range(len(s)//2):\n            start = int(s[2*i]) - 1\n            length = int(s[2*i + 1])\n            img[start:start+length] = 1+m\n    return img.reshape(shape).T\n\ndef mask2enc(mask, n = 1):\n    pixels = mask.T.flatten()\n    encs = []\n    for i in range(1, n+1):\n        p = (pixels == i).astype(np.int8)\n        if p.sum() == 0: \n            encs.append(np.nan)\n        else:\n            p = np.concatenate([[0], p, [0]])\n            runs = np.where(p[1:] != p[:-1])[0] + 1\n            runs[1::2] -= runs[::2]\n            encs.append(' '.join(str(x) for x in runs))\n    return encs\n\ndf_masks = pd.read_csv(MASKS).set_index('id')\ndf_masks.head()\n            ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"s_th = 40  #saturation blancking threshold\np_th = 200*sz//256 #threshold for the minimum number of pixels\n\nx_tot,x2_tot = [],[]\nwith zipfile.ZipFile(OUT_TRAIN, 'w') as img_out,\\\n zipfile.ZipFile(OUT_MASKS, 'w') as mask_out:\n    for index, encs in tqdm(df_masks.iterrows(),total=len(df_masks)):\n        #read image and generate the mask\n        img = tifffile.imread(os.path.join(DATA,index+'.tiff'))\n        if len(img.shape) == 5: img = np.transpose(img.squeeze(), (1,2,0))\n        mask = enc2mask(encs,(img.shape[1],img.shape[0]))\n\n        #add padding to make the image dividable into tiles\n        shape = img.shape\n        pad0 = (reduce*sz - shape[0]%(reduce*sz))%(reduce*sz)\n        pad1 = (reduce*sz - shape[1]%(reduce*sz))%(reduce*sz)\n        img = np.pad(img,[[pad0//2,pad0-pad0//2],[pad1//2,pad1-pad1//2],[0,0]],\n                    constant_values=0)\n        mask = np.pad(mask,[[pad0//2,pad0-pad0//2],[pad1//2,pad1-pad1//2]],\n                    constant_values=0)\n\n        #split image and mask into tiles using the reshape+transpose trick\n        img = cv2.resize(img,(img.shape[1]//reduce,img.shape[0]//reduce),\n                         interpolation = cv2.INTER_AREA)\n        img = img.reshape(img.shape[0]//sz,sz,img.shape[1]//sz,sz,3)\n        img = img.transpose(0,2,1,3,4).reshape(-1,sz,sz,3)\n\n        mask = cv2.resize(mask,(mask.shape[1]//reduce,mask.shape[0]//reduce),\n                          interpolation = cv2.INTER_NEAREST)\n        mask = mask.reshape(mask.shape[0]//sz,sz,mask.shape[1]//sz,sz)\n        mask = mask.transpose(0,2,1,3).reshape(-1,sz,sz)\n\n        #write data\n        for i,(im,m) in enumerate(zip(img,mask)):\n            #remove black or gray images based on saturation check\n            hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)\n            h, s, v = cv2.split(hsv)\n            if (s>s_th).sum() <= p_th or im.sum() <= p_th: continue\n            \n            x_tot.append((im/255.0).reshape(-1,3).mean(0))\n            x2_tot.append(((im/255.0)**2).reshape(-1,3).mean(0))\n            \n            im = cv2.imencode('.png',cv2.cvtColor(im, cv2.COLOR_RGB2BGR))[1]\n            img_out.writestr(f'{index}_{i}.png', im)\n            m = cv2.imencode('.png',m)[1]\n            mask_out.writestr(f'{index}_{i}.png', m)\n\n#image stats\nimg_avr =  np.array(x_tot).mean(0)\nimg_std =  np.sqrt(np.array(x2_tot).mean(0) - img_avr**2)\nprint('mean:',img_avr, ', std:', img_std)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 4. Image and Masks Visualizations"},{"metadata":{"trusted":true},"cell_type":"code","source":"small_ids = [\n    \"0486052bb\", \"095bf7a1f\", \"1e2425f28\", \"2f6ecfcdf\",\n    \"54f2eec69\", \"aaa6a05cc\", \"cb2d976f4\", \"e79de561c\",\n]\nsmall_images = []\nsmall_masks = []\n\nfor small_id in small_ids:\n    tmp_image, tmp_mask = read_image(small_id, scale = 20, verbose = 0)\n    small_images.append(tmp_image)\n    small_masks.append(tmp_mask)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**4.1 Train Images**"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(16, 16))\nfor ind, (tmp_id, tmp_image) in enumerate(zip(small_ids, small_images)):\n    plt.subplot(3, 3, ind+1)\n    plt.imshow(tmp_image)\n    plt.axis(\"off\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**4.2 Train images and masks**"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (16, 16))\nfor ind, (tmp_id, tmp_image, tmp_mask) in enumerate(zip(small_ids, small_images, small_masks)):\n    plt.subplot(3, 3, ind + 1)\n    plt.imshow(tmp_image)\n    plt.imshow(tmp_mask, cmap=\"hot\", alpha = 0.5)\n    plt.axis(\"off\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"small_ids = [\n    \"26dc41664\", \"afa5e8098\", \"b2dc8411c\", \"b9a3865fc\", \"c68fe75ea\",\n]\nsmall_images = []\nfor small_id in small_ids:\n    tmp_image = read_test_image(small_id, scale = 20, verbose = 0)\n    small_images.append(tmp_image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**4.3 Test Images**"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(16,11))\nfor ind, (tmp_id, tmp_image) in enumerate(zip(small_ids, small_images)):\n    plt.subplot(2, 3, ind + 1)\n    plt.imshow(tmp_image)\n    plt.axis(\"off\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**4.4 Plot Image and Mask**"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_id = \"0486052bb\"\nimage, mask = read_image(image_id, 3)\nplot_image_and_mask(image, mask, image_id)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**4.5 Plot Sliced Image and Mask**"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_slice_image_and_mask(image, mask, 5000, 7000, 2000, 5000)\nplot_slice_image_and_mask(image, mask, 5250, 6000, 3000, 4000)\nplot_slice_image_and_mask(image, mask, 5370, 5700, 3500, 3800)\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**4.6 Plot Grid Image with Mask**"},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_grid_image_with_mask(image, mask)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"columns, rows = 4,4\nidx0 = 20\nfig=plt.figure(figsize=(columns*4, rows*4))\nwith zipfile.ZipFile(OUT_TRAIN, 'r') as img_arch, \\\nzipfile.ZipFile(OUT_MASKS, 'r') as msk_arch:\n    fnames = sorted(img_arch.namelist())[8:]\n    for i in range(rows):\n        for j in range(columns):\n            idx = i + j*columns\n            img = cv2.imdecode(np.frombuffer(img_arch.read(fnames[idx0+idx]), np.uint8), cv2.IMREAD_COLOR)\n            img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)\n            mask = cv2.imdecode(np.frombuffer(msk_arch.read(fnames[idx0+idx]), np.uint8), cv2.IMREAD_GRAYSCALE)\n            \n            fig.add_subplot(rows, columns, idx +1)\n            plt.axis('off')\n            plt.imshow(Image.fromarray(img))\n            plt.imshow(Image.fromarray(mask), alpha=0.2)\n            \nplt.show()            ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 5. Metadata Analysis"},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.read_json(os.path.join(BASE_PATH, \"train/0486052bb-anatomical-structure.json\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.read_json(os.path.join(BASE_PATH, \"train/0486052bb.json\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_info[\"split\"] = \"test\"\ndf_info.loc[df_info[\"image_file\"].isin(os.listdir(os.path.join(BASE_PATH, \"train\"))), \"split\"] = \"train\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_info[\"area\"] = df_info[\"width_pixels\"] * df_info[\"height_pixels\"]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_info.head(3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 6. References \n\nhttps://www.kaggle.com/ihelon/hubmap-exploratory-data-analysis\n\nhttps://www.kaggle.com/iafoss/256x256-images\n"}],"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":4}