{"cells":[{"metadata":{"papermill":{"duration":0.018998,"end_time":"2021-01-31T11:44:38.653319","exception":false,"start_time":"2021-01-31T11:44:38.634321","status":"completed"},"tags":[]},"cell_type":"markdown","source":"<h1 style=\"text-align: center; font-family: Verdana; font-size: 32px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; font-variant: small-caps; letter-spacing: 3px; color: #74d5dd; background-color: #ffffff;\">Human Protein Atlas - Single Cell Classification</h1>\n<h2 style=\"text-align: center; font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: underline; text-transform: none; letter-spacing: 2px; color: navy; background-color: #ffffff;\">Categorical Classification At a Cellular Level [TRAINING]</h2>\n<h5 style=\"text-align: center; font-family: Verdana; font-size: 12px; font-style: normal; font-weight: bold; text-decoration: None; text-transform: none; letter-spacing: 1px; color: black; background-color: #ffffff;\">CREATED BY: DARIEN SCHETTLER</h5>\n\n<br><br>"},{"metadata":{"papermill":{"duration":0.0173,"end_time":"2021-01-31T11:44:38.723672","exception":false,"start_time":"2021-01-31T11:44:38.706372","status":"completed"},"tags":[]},"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; background-color: #ffffff; color: navy;\" id=\"imports\">0&nbsp;&nbsp;IMPORTS&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"#toc\">&#10514;</a></h1>"},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.execute_input":"2021-01-31T11:44:38.778565Z","iopub.status.busy":"2021-01-31T11:44:38.773342Z","iopub.status.idle":"2021-01-31T11:45:56.057076Z","shell.execute_reply":"2021-01-31T11:45:56.056378Z"},"papermill":{"duration":77.315718,"end_time":"2021-01-31T11:45:56.057286","exception":false,"start_time":"2021-01-31T11:44:38.741568","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"print(\"\\n... OTHER IMPORTS STARTING ...\\n\")\nprint(\"\\n\\tVERSION INFORMATION\")\n\n# Machine Learning and Data Science Imports\nimport tensorflow_addons as tfa; print(f\"\\t\\t– TENSORFLOW ADDONS VERSION: {tfa.__version__}\");\nimport tensorflow as tf; print(f\"\\t\\t– TENSORFLOW VERSION: {tf.__version__}\");\nimport pandas as pd; pd.options.mode.chained_assignment = None;\nimport numpy as np; print(f\"\\t\\t– NUMPY VERSION: {np.__version__}\");\nimport scipy; print(f\"\\t\\t– SCIPY VERSION: {scipy.__version__}\");\n\n# Built In Imports\nfrom collections import Counter\nfrom datetime import datetime\nimport multiprocessing\nfrom glob import glob\nimport warnings\nimport requests\nimport imageio\nimport IPython\nimport urllib\nimport zipfile\nimport pickle\nimport random\nimport shutil\nimport string\nimport math\nimport tqdm\nimport time\nimport gzip\nimport io\nimport os\nimport gc\nimport re\n\n# Visualization Imports\nfrom matplotlib.colors import ListedColormap\nimport matplotlib.patches as patches\nimport plotly.graph_objects as go\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm\nimport plotly.express as px\nimport seaborn as sns\nfrom PIL import Image\nimport matplotlib; print(f\"\\t\\t– MATPLOTLIB VERSION: {matplotlib.__version__}\");\nimport plotly\nimport PIL\nimport cv2\nimport ast\n\n# PRESETS\nLBL_NAMES = [\"Nucleoplasm\", \"Nuclear Membrane\", \"Nucleoli\", \"Nucleoli Fibrillar Center\", \"Nuclear Speckles\", \"Nuclear Bodies\", \"Endoplasmic Reticulum\", \"Golgi Apparatus\", \"Intermediate Filaments\", \"Actin Filaments\", \"Microtubules\", \"Mitotic Spindle\", \"Centrosome\", \"Plasma Membrane\", \"Mitochondria\", \"Aggresome\", \"Cytosol\", \"Vesicles\", \"Negative\"]\nINT_2_STR = {x:LBL_NAMES[x] for x in np.arange(19)}\nINT_2_STR_LOWER = {k:v.lower().replace(\" \", \"_\") for k,v in INT_2_STR.items()}\nSTR_2_INT_LOWER = {v:k for k,v in INT_2_STR_LOWER.items()}\nSTR_2_INT = {v:k for k,v in INT_2_STR.items()}\nFIG_FONT = dict(family=\"Helvetica, Arial\", size=14, color=\"#7f7f7f\")\nLABEL_COLORS = [px.colors.label_rgb(px.colors.convert_to_RGB_255(x)) for x in sns.color_palette(\"Spectral\", len(LBL_NAMES))]\nLABEL_COL_MAP = {str(i):x for i,x in enumerate(LABEL_COLORS)}\n\nprint(\"\\n\\n... IMPORTS COMPLETE ...\\n\")","execution_count":null,"outputs":[]},{"metadata":{"papermill":{"duration":0.020391,"end_time":"2021-01-31T11:45:56.263882","exception":false,"start_time":"2021-01-31T11:45:56.243491","status":"completed"},"tags":[]},"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; color: navy; background-color: #ffffff;\" id=\"setup\">2&nbsp;&nbsp;NOTEBOOK SETUP&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"#toc\">&#10514;</a></h1>"},{"metadata":{"execution":{"iopub.execute_input":"2021-01-31T11:45:56.320967Z","iopub.status.busy":"2021-01-31T11:45:56.319646Z","iopub.status.idle":"2021-01-31T11:45:58.177889Z","shell.execute_reply":"2021-01-31T11:45:58.177292Z"},"papermill":{"duration":1.893314,"end_time":"2021-01-31T11:45:58.178032","exception":false,"start_time":"2021-01-31T11:45:56.284718","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"# Define the path to the root data directory\nROOT_DIR = \"/kaggle/input\"\nOUTPUT_DIR = \"/kaggle\"\n\n# Define the path to the competition data directory\nCOMP_DIR = os.path.join(ROOT_DIR, \"hpa-single-cell-image-classification\")\n\n\nCOLORS=[\"red\", \"green\", \"blue\", \"yellow\"]\nTILE_OUTPUT_DIRS = [os.path.join(OUTPUT_DIR, f\"{c}_tiles\") for c in COLORS]\nfor OUTPUT_DIR in TILE_OUTPUT_DIRS:\n    for k in STR_2_INT_LOWER.keys():\n        os.makedirs(os.path.join(OUTPUT_DIR, k), exist_ok=True)\n\n# Define the paths to the training and testing tfrecord and \n# image folders respectively for the competition data\nTRAIN_IMG_DIR = os.path.join(COMP_DIR, \"train\")\n\n# Capture all the relevant full image paths for the competition dataset\nTRAIN_IMG_PATHS = sorted([os.path.join(TRAIN_IMG_DIR, f_name) for f_name in os.listdir(TRAIN_IMG_DIR)])\n\n# Define paths to the relevant csv files\nTRAIN_CSV = os.path.join(ROOT_DIR, \"hpa-train-data-with-additional-metadata/updated_train.csv\")\n\nprint(\"\\n... Loading Massive Train Dataframe ...\\n\")\n# Create the relevant dataframe objects\ntrain_df = pd.read_csv(TRAIN_CSV)\ntrain_df.drop(columns=[\"mask_rles\"], inplace=True)\ntrain_df = train_df[train_df.Label.str.count(\"\\|\")==0].reset_index(drop=True)\ntrain_df.mask_bboxes = train_df.mask_bboxes.apply(lambda x: ast.literal_eval(x))\n\nprint(\"\\n\\nTRAIN DATAFRAME\\n\\n\")\ndisplay(train_df.head(3))","execution_count":null,"outputs":[]},{"metadata":{"papermill":{"duration":0.022604,"end_time":"2021-01-31T11:45:58.224086","exception":false,"start_time":"2021-01-31T11:45:58.201482","status":"completed"},"tags":[]},"cell_type":"markdown","source":"<h1 style=\"font-family: Verdana; font-size: 24px; font-style: normal; font-weight: bold; text-decoration: none; text-transform: none; letter-spacing: 3px; color: navy; background-color: #ffffff;\" id=\"helper_functions\">3&nbsp;&nbsp;HELPER FUNCTIONS&nbsp;&nbsp;&nbsp;&nbsp;<a href=\"#toc\">&#10514;</a></h1>"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","execution":{"iopub.execute_input":"2021-01-31T11:45:58.303779Z","iopub.status.busy":"2021-01-31T11:45:58.291581Z","iopub.status.idle":"2021-01-31T11:46:01.296299Z","shell.execute_reply":"2021-01-31T11:46:01.295762Z"},"papermill":{"duration":3.049332,"end_time":"2021-01-31T11:46:01.296459","exception":false,"start_time":"2021-01-31T11:45:58.247127","status":"completed"},"tags":[],"trusted":true},"cell_type":"code","source":"def load_image_color(img_id, img_dir, color):\n    \"\"\" Load An Image To Be Tiled \"\"\"\n    return cv2.imread(os.path.join(img_dir, img_id+f\"_{color}.png\"), 0)\n\n\ndef load_image(img_id, img_dir):\n    \"\"\" Load An Image Using ID and Directory Path - Composes 4 Individual Images \"\"\"\n    return np.stack(\n        [np.asarray(cv2.imread(os.path.join(img_dir, img_id+f\"_{c}.png\"), 0)/255.) for c in [\"red\", \"green\", \"blue\", \"yellow\"]], axis=-1\n    )\n\n    \ndef convert_rgby_to_rgb(arr):\n    \"\"\" Convert a 4 channel (RGBY) image to a 3 channel RGB image.\n    \n    Advice From Competition Host/User: lnhtrang\n\n    For annotation (by experts) and for the model, I guess we agree that individual \n    channels with full range px values are better. \n    In annotation, we toggled the channels. \n    For visualization purpose only, you can try blending the channels. \n    For example, \n        - red = red + yellow\n        - green = green + yellow/2\n        - blue=blue.\n        \n    Args:\n        arr (numpy array): The RGBY, 4 channel numpy array for a given image\n    \n    Returns:\n        RGB Image\n    \"\"\"\n    \n    rgb_arr = np.zeros_like(arr[..., :-1])\n    rgb_arr[..., 0] = arr[..., 0]\n    rgb_arr[..., 1] = arr[..., 1]+arr[..., 3]/2\n    rgb_arr[..., 2] = arr[..., 2]\n    \n    return rgb_arr\n    \n    \ndef plot_ex(arr, figsize=(20,6), title=None, plot_merged=True, rgb_only=False):\n    \"\"\" Plot 4 Channels Side by Side \"\"\"\n    if plot_merged and not rgb_only:\n        n_images=5 \n    elif plot_merged and rgb_only:\n        n_images=4\n    elif not plot_merged and rgb_only:\n        n_images=4\n    else:\n        n_images=3\n    plt.figure(figsize=figsize)\n    if type(title) == str:\n        plt.suptitle(title, fontsize=20, fontweight=\"bold\")\n\n    for i, c in enumerate([\"Red Channel – Microtubles\", \"Green Channel – Protein of Interest\", \"Blue - Nucleus\", \"Yellow – Endoplasmic Reticulum\"]):\n        if not rgb_only:\n            ch_arr = np.zeros_like(arr[..., :-1])        \n        else:\n            ch_arr = np.zeros_like(arr)\n        if c in [\"Red Channel – Microtubles\", \"Green Channel – Protein of Interest\", \"Blue - Nucleus\"]:\n            ch_arr[..., i] = arr[..., i]\n        else:\n            if rgb_only:\n                continue\n            ch_arr[..., 0] = arr[..., i]\n            ch_arr[..., 1] = arr[..., i]\n        plt.subplot(1,n_images,i+1)\n        plt.title(f\"{c.title()}\", fontweight=\"bold\")\n        plt.imshow(ch_arr)\n        plt.axis(False)\n        \n    if plot_merged:\n        plt.subplot(1,n_images,n_images)\n        \n        if rgb_only:\n            plt.title(f\"Merged RGB\", fontweight=\"bold\")\n            plt.imshow(arr)\n        else:\n            plt.title(f\"Merged RGBY into RGB\", fontweight=\"bold\")\n            plt.imshow(convert_rgby_to_rgb(arr))\n        plt.axis(False)\n        \n    plt.tight_layout(rect=[0, 0.2, 1, 0.97])\n    plt.show()\n    \n    \ndef flatten_list_of_lists(l_o_l):\n    return [item for sublist in l_o_l for item in sublist]\n\n\ndef pad_to_square(a, is_2d=False):\n    \"\"\" Pad an array `a` evenly until it is a square \"\"\"\n    if a.shape[1]>a.shape[0]: # pad height\n        n_to_add = a.shape[1]-a.shape[0]\n        top_pad = n_to_add//2\n        bottom_pad = n_to_add-top_pad\n        if is_2d:\n            a = np.pad(a, [(top_pad, bottom_pad), (0, 0)], mode='constant')\n        else:\n            a = np.pad(a, [(top_pad, bottom_pad), (0, 0), (0, 0)], mode='constant')\n    elif a.shape[0]>a.shape[1]: # pad width\n        n_to_add = a.shape[0]-a.shape[1]\n        left_pad = n_to_add//2\n        right_pad = n_to_add-left_pad\n        if is_2d:\n            a = np.pad(a, [(0, 0), (left_pad, right_pad)], mode='constant')\n        else:\n            a = np.pad(a, [(0, 0), (left_pad, right_pad), (0, 0)], mode='constant')\n    else:\n        pass\n    return a\n\n\ndef get_cell_tiles_from_id(img_id, bboxes, tile_size=(128,128), color=\"red\"):\n    img = load_image_color(img_id, TRAIN_IMG_DIR, color)\n    batch_cell_tiles = [\n        cv2.resize(\n            pad_to_square(img[bbox[1]:bbox[3], bbox[0]:bbox[2], ...], is_2d=True), \n                   tile_size, interpolation=cv2.INTER_CUBIC\n        ) for bbox in bboxes\n    ]\n    return batch_cell_tiles\n\n\ndef img_id_to_save_files(output_dir, img_id, bboxes, lbl, tile_size=(128,128), color=\"red\"):\n    out_dir_path = os.path.join(output_dir, INT_2_STR_LOWER[int(lbl)])\n    cell_tiles = get_cell_tiles_from_id(img_id, bboxes, tile_size, color)\n    for i, tile in enumerate(cell_tiles):\n        cv2.imwrite(os.path.join(out_dir_path, f\"{img_id}_{i+1:02}.png\"), tile)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get requisite arrays\ntrain_arr = train_df[[\"ID\", \"Label\", \"mask_bboxes\"]].values\ntrain_ids = train_arr[:, 0]\ntrain_labels = train_arr[:, 1]\ntrain_bboxes = train_arr[:, 2]\n\n# Loop over and generate the tiles\nfor clr, out_dir in tqdm(zip(COLORS, TILE_OUTPUT_DIRS), total=len(COLORS)):\n    for _id, _bboxes, _lbl in tqdm(zip(train_ids, train_bboxes, train_labels), total=len(train_ids)):\n        img_id_to_save_files(out_dir, _id, _bboxes, _lbl, color=clr)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!du -sh ./\n!zip -r tile_dataset.zip /kaggle/red_tiles /kaggle/green_tiles /kaggle/blue_tiles /kaggle/yellow_tiles\n!rm -rf /kaggle/*tiles\n!du -sh ./","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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":4}