{"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":"![](https://i.ibb.co/7t6wKN7/000.png)","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <b>Introduction 👁</b>\n    <br>The proper functioning of your body's organs and tissues depends on the interaction, spatial organization, and specialization of your cells—all 37 trillion of them. With so many cells, determining their functions and relationships is a monumental undertaking.<br>\n    <br>Current efforts to map cells involve the Vasculature Common Coordinate Framework (VCCF), which uses the blood vasculature in the human body as the primary navigation system. The VCCF crosses all scale levels--from the whole body to the single cell level--and provides a unique way to identify cellular locations using capillary structures as an address. However, the gaps in what researchers know about microvasculature lead to gaps in the VCCF. If we could automatically segment microvasculature arrangements, researchers could use the real-world tissue data to begin to fill in those gaps and map out the vasculature.<br>\n    <br>Competition host Human BioMolecular Atlas Program (HuBMAP) hopes to develop an open and global platform to map healthy cells in the human body. Using the latest molecular and cellular biology technologies, HuBMAP researchers are studying the connections that cells have with each other throughout the body.<br>\n    <br>There are still many unknowns regarding microvasculature, but your Machine Learning insights could enable researchers to use the available tissue data to augment their understanding of how these small vessels are arranged throughout the body. Ultimately, you'll be helping to pave the way towards building a Vascular Common Coordinate Framework (VCCF) and a Human Reference Atlas (HRA), which will identify how the relationships between cells can affect our health.<br>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Exploratory Data Analysis  📚</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\"><h1>Data Description</h1>\n<p>Your goal in this competition is to locate microvasculature structures (blood vessels) within human kidney histology slides.</p>\n<p>The competition data comprises tiles extracted from five Whole Slide Images (WSI) split into two datasets. Tiles from Dataset 1 have annotations that have been expert reviewed. Dataset 2 comprises the remaining tiles from these same WSIs and contain sparse annotations that have not been expert reviewed.</p>\n<ul>\n<li>All of the test set tiles are from Dataset 1.</li>\n<li>Two of the WSIs make up the training set, two WSIs make up the public test set, and one WSI makes up the private test set.</li>\n<li>The training data includes Dataset 2 tiles from the <em>public</em> test WSI, but <em>not</em> from the <em>private</em> test WSI.</li>\n</ul>\n<p>We also include, as Dataset 3, tiles extracted from an additional nine WSIs. These tiles have not been annotated. You may wish to apply semi- or self-supervised learning techniques on this data to support your predictions.</p>\n<p>Note that this is a <a target=\"_blank\" href=\"https://www.kaggle.com/competitions/hubmap-hacking-the-human-vasculature/overview/code-requirements\"><strong>Code Competition</strong></a>, in which the actual test set is hidden. In this version, we give some sample data drawn from the public test set to help you author your solutions. When your submission is scored, this example test data will be replaced with the full test set. There are about 650 tiles in the full test set.</p>\n<p>You may find resources from the previous HuBMAP competitions useful as well:</p>\n<ul>\n<li><a target=\"_blank\" href=\"https://www.kaggle.com/competitions/hubmap-kidney-segmentation/\">HuBMAP: Hacking the Kidney</a></li>\n<li><a target=\"_blank\" href=\"https://www.kaggle.com/competitions/hubmap-organ-segmentation/\">HuBMAP + HPA: Hacking the Human Body</a></li>\n</ul>\n<h2>Files and Field Descriptions</h2>\n<ul>\n<li><strong>{train|test}/</strong> Folders containing TIFF images of the tiles. Each tile is 512x512 in size.</li>\n<li><strong>polygons.jsonl</strong> Polygonal segmentation masks in JSONL format, available for Dataset 1 and Dataset 2. Each line gives JSON annotations for a single image with:<ul>\n<li><code>id</code> Identifies the corresponding image in <strong>train/</strong></li>\n<li><code>annotations</code>  A list of mask annotations with:</li>\n<li><code>type</code> Identifies the type of structure annotated:<ul>\n<li><code>blood_vessel</code> The target structure. Your goal in this competition is to predict these kinds of masks on the test set.</li>\n<li><code>glomerulus</code> A capillary ball structure in the kidney. These parts of the images were excluded from blood vessel annotation. You should ensure none of your test set predictions occur within glomerulus structures as they will be counted as false positives. Annotations are provided for test set tiles.</li>\n<li><code>unsure</code> A structure the expert annotators cannot confidently distinguish as a blood vessel.</li></ul></li>\n<li><code>coordinates</code> A list of polygon coordinates defining the segmentation mask.</li></ul></li>\n<li><strong>tile_meta.csv</strong> Metadata for each image.<ul>\n<li><code>source_wsi</code> Identifies the WSI this tile was extracted from.</li>\n<li><code>{i|j}</code> The location of the upper-left corner within the WSI where the tile was extracted.</li>\n<li><code>dataset</code> The dataset this tile belongs to, as described above.</li></ul></li>\n<li><strong>wsi_meta.csv</strong> Metadata for the Whole Slide Images the tiles were extracted from.<ul>\n<li><code>source_wsi</code> Identifies the WSI.</li>\n<li><code>age</code>, <code>sex</code>, <code>race</code>, <code>height</code>, <code>weight</code>, and <code>bmi</code> demographic information about the tissue donor.</li></ul></li>\n<li><strong>sample_submission.csv</strong> A sample submission file in the correct format. See the <a target=\"_blank\" href=\"https://www.kaggle.com/competitions/hubmap-hacking-the-human-vasculature/overview/evaluation\"><strong>Evaluation</strong></a> page for more details.</li>\n</ul></div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Biological Overview 🔬</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"![](https://i.gifer.com/2zFp.gif)","metadata":{}},{"cell_type":"markdown","source":"![](https://i.ibb.co/1MZNhNF/003.png)","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <b>Tissue samples 🧪</b>\n    <br>Renal cortex: the renal cortex is the outer portion of the kidney that contains round renal corpuscles enclosing glomerular tufts, balls of capillary loops. The renal corpuscle is the start of the nephron, through which the filtration of blood occurs. The renal cortex also contains proximal and distal convoluted tubules, PCTs and DCTs, which are also regions of the nephron. Between these tubular structures is a complex network of capillaries called the peritubular capillaries.<br>\n    <br>Renal medulla: the renal medulla is the inner portion of the kidney and is arranged in 8-15 renal pyramids containing linearly arranged tubules comprising the loops of Henle and ducts that gather products for excretion. The capillary network in the renal medulla consists of capillaries called vasa recta. The renal pyramids (medullary tissue) are divided by extensions of the renal cortex called renal columns. There are also projections of the renal medulla into the outer cortex called medullary rays.<br>\n    <br>Renal papilla (subsection of medulla): the broad bases of the pyramids connect to the renal cortex at the corticomedullary junctions while the tips form structures called the renal papilla, which project in the minor renal calyces where urine is collected.<br>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Libraries ⚒</b>\n</div>","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt \nimport numpy as np\nimport os \nimport pandas as pd \nfrom tqdm import tqdm, notebook \nfrom collections import Counter\nimport warnings ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"warnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:15.654834Z","iopub.execute_input":"2023-08-11T12:21:15.655262Z","iopub.status.idle":"2023-08-11T12:21:15.660664Z","shell.execute_reply.started":"2023-08-11T12:21:15.655233Z","shell.execute_reply":"2023-08-11T12:21:15.659477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Pathes 🧶</b>\n</div>","metadata":{}},{"cell_type":"code","source":"# Files \n__SAMPLE_SBMISSION_PATH = \"/kaggle/input/hubmap-hacking-the-human-vasculature/sample_submission.csv\"\n__TILE_META_PATH = \"/kaggle/input/hubmap-hacking-the-human-vasculature/tile_meta.csv\"\n__WSI_META_PATH = \"/kaggle/input/hubmap-hacking-the-human-vasculature/wsi_meta.csv\"\n__ANNOTATION_PATH = \"/kaggle/input/hubmap-hacking-the-human-vasculature/polygons.jsonl\"\n__DATASET_CONFIG_PATH = \"/kaggle/working/classes_config.csv\" # Custom file\n\n# Folders\n__TRAIN_PATH = \"/kaggle/input/hubmap-hacking-the-human-vasculature/train\"\n__TEST_PATH = \"/kaggle/input/hubmap-hacking-the-human-vasculature/test\"","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:18.356087Z","iopub.execute_input":"2023-08-11T12:21:18.356984Z","iopub.status.idle":"2023-08-11T12:21:18.362538Z","shell.execute_reply.started":"2023-08-11T12:21:18.356943Z","shell.execute_reply":"2023-08-11T12:21:18.361374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission = pd.read_csv(__SAMPLE_SBMISSION_PATH)\ntile_meta = pd.read_csv(__TILE_META_PATH)\nwsi_meta = pd.read_csv(__WSI_META_PATH)","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:20.405247Z","iopub.execute_input":"2023-08-11T12:21:20.405707Z","iopub.status.idle":"2023-08-11T12:21:20.466106Z","shell.execute_reply.started":"2023-08-11T12:21:20.405651Z","shell.execute_reply":"2023-08-11T12:21:20.464587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    Submissions are evaluated by computing the Average Precision over confidence scores. It is identical to the <a target=\"_blank\" href=\"https://www.kaggle.com/c/open-images-2019-instance-segmentation/overview/evaluation\">OpenImages Instance Segmentation Challenge evaluation</a>, though with only a single class. The OpenImages version of the metric is <a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"https://storage.googleapis.com/openimages/web/evaluation.html#instance_segmentation_eval\">described in detail here</a>. See also <a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/challenge_evaluation.md#instance-segmentation-track\">this tutorial</a> on running the evaluation in Python.</p>\n<p>Segmentation is calculated using IoU with a threshold of <code>0.6</code>.</p>\n</div>","metadata":{}},{"cell_type":"code","source":"sample_submission","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:22.534542Z","iopub.execute_input":"2023-08-11T12:21:22.534983Z","iopub.status.idle":"2023-08-11T12:21:22.567573Z","shell.execute_reply.started":"2023-08-11T12:21:22.534954Z","shell.execute_reply":"2023-08-11T12:21:22.566443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"sc-dmLtQE jWwnsR\"><p>\n<h2>Submission File</h2>\n<p>For each image in the test set, you must predict a list of instance segmentation masks and their associated detection score (<code>Confidence</code>). The <code>submission.csv</code> file uses the following format:</p>\n<pre><code><span class=\"hljs-attribute\">id</span>,height,width,prediction_string\n<span class=\"hljs-attribute\">72e40acccadf</span>,<span class=\"hljs-number\">512</span>,<span class=\"hljs-number\">512</span>,<span class=\"hljs-number\">0</span> <span class=\"hljs-number\">1</span>.<span class=\"hljs-number\">0</span> eNoLTDAwyrM3yI/PMwcAE94DZA==\n</code></pre>\n<p>where <code>prediction_string</code> has the format <code>0 {confidence} {EncodedMask}</code>. Note that the metric has several \"boilerplate\" values needed to adapt it to this competition; namely, the <code>height</code>, <code>width</code>, and the leading <code>0</code> in <code>prediction_string</code>, which ordinarily is a class label.</p>\n<p>Separate prediction strings multiple instance masks for the same image with a space, like so:</p>\n<pre><code><span class=\"hljs-attribute\">id</span>,height,width,prediction_string\n<span class=\"hljs-attribute\">72e40acccadf</span>,<span class=\"hljs-number\">512</span>,<span class=\"hljs-number\">512</span>,<span class=\"hljs-number\">0</span> <span class=\"hljs-number\">1</span>.<span class=\"hljs-number\">0</span> eNoLTDAwyrM3yI/PMwcAE94DZA== <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">5</span> eAndnnDS1A/mdmkE35Ek9d\n</code></pre>\n<p>The binary segmentation masks are <a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Run-length_encoding\">run-length encoded</a> (RLE), <a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Zlib\">zlib</a> compressed, and <a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Base64\">base64</a> encoded to be used in text format as <code>EncodedMask</code>. Specifically, we use the Coco masks RLE encoding/decoding (see the <code>encode</code> method of <a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"http://cocodataset.org/#download\">COCO’s mask API</a>), the zlib compression/decompression (<a rel=\"noreferrer nofollow\" target=\"_blank\" href=\"https://www.ietf.org/rfc/rfc1950.txt\">RFC1950</a>), and vanilla base64 encoding.</p>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Tile meta</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <br>The competition data includes small pieces called \"tiles\" that come from five big pictures called \"Whole Slide Images\" (WSI). These WSIs are split into two groups called datasets. In Dataset 1, the tiles have been looked at by experts who reviewed and marked them. In Dataset 2, the tiles are from the same big pictures but they don't have as many marks, and the marks they do have haven't been reviewed by experts.<br>\n</div>","metadata":{}},{"cell_type":"code","source":"tile_meta","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:26.614654Z","iopub.execute_input":"2023-08-11T12:21:26.615432Z","iopub.status.idle":"2023-08-11T12:21:26.629012Z","shell.execute_reply.started":"2023-08-11T12:21:26.615395Z","shell.execute_reply":"2023-08-11T12:21:26.628171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset_count = tile_meta['dataset'].value_counts()\n\nplt.stackplot(list(map(str, dataset_count.index)), dataset_count.values)\n\nplt.xlabel('Dataset Number')\nplt.ylabel('Number of Examples')\nplt.title('Number of examples in each dataset')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:29.674922Z","iopub.execute_input":"2023-08-11T12:21:29.675594Z","iopub.status.idle":"2023-08-11T12:21:29.971210Z","shell.execute_reply.started":"2023-08-11T12:21:29.675556Z","shell.execute_reply":"2023-08-11T12:21:29.969765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Wsi meta</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <br>Whole Slide Images (WSIs), also known as virtual slides or digital slides, refer to high-resolution digital representations of entire histopathology glass slides. These slides are typically generated by scanning glass slides using specialized slide scanners.<br>\n    <br>We should expect 14 unique sources of WSIs where 5 have been used for annotations by either a expert or non expert which then get put into dataset 1 and 2 respectively, and the other 9 correspond to WSIs for dataset 3 which have no annotations. Although we should expect 14 we see that there is only thirteen. A keen eye would see that number 5 is missing. This is probably because the 5th WSI belongs to the first dataset and was removed from the dataset to be used as the test set.<br>\n</div>","metadata":{}},{"cell_type":"markdown","source":"## Distribution of WSI by datasets\n![](https://i.ibb.co/6Y1zJvv/001.png)","metadata":{}},{"cell_type":"markdown","source":"## Legend \n![](https://i.ibb.co/gghC5LZ/002.png)","metadata":{}},{"cell_type":"code","source":"wsi_meta","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:35.294818Z","iopub.execute_input":"2023-08-11T12:21:35.295309Z","iopub.status.idle":"2023-08-11T12:21:35.313400Z","shell.execute_reply.started":"2023-08-11T12:21:35.295265Z","shell.execute_reply":"2023-08-11T12:21:35.311834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sex_counts = wsi_meta.sex.value_counts()\nrace_counts = wsi_meta.race.value_counts()\n\nfig, (ax1, ax2) = plt.subplots(1, 2)\n\nax1.pie(sex_counts.values, labels=sex_counts.index, autopct='%1.1f%%')\nax1.set_title(\"Distribution of Sexes\")\n\nax2.pie(race_counts.values, labels=race_counts.index, autopct='%1.1f%%')\nax2.set_title(\"Distribution of races\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:37.335413Z","iopub.execute_input":"2023-08-11T12:21:37.335891Z","iopub.status.idle":"2023-08-11T12:21:37.719403Z","shell.execute_reply.started":"2023-08-11T12:21:37.335857Z","shell.execute_reply":"2023-08-11T12:21:37.717593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sex_counts = wsi_meta.sex.value_counts()\nrace_counts = wsi_meta.race.value_counts()\n\nfig, (ax1, ax2) = plt.subplots(1, 2)\n\nax1.specgram(sex_counts.values)\nax1.set_title(\"Distribution of Sexes\")\n\n# ax2.pie(race_counts.values, labels=race_counts.index, autopct='%1.1f%%')\n# ax2.set_title(\"Distribution of races\")\n\nax2.specgram(race_counts.values)\nax2.set_title(\"Distribution of races\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:39.616572Z","iopub.execute_input":"2023-08-11T12:21:39.617073Z","iopub.status.idle":"2023-08-11T12:21:40.063330Z","shell.execute_reply.started":"2023-08-11T12:21:39.617040Z","shell.execute_reply":"2023-08-11T12:21:40.062100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sex_counts = wsi_meta.sex.value_counts()\nrace_counts = wsi_meta.race.value_counts()\n\nfig, (ax1, ax2) = plt.subplots(1, 2)\n\nax1.violinplot(sex_counts.values)\nax1.set_title(\"Distribution of Sexes\")\n\nax2.violinplot(race_counts.values)\nax2.set_title(\"Distribution of races\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:41.605994Z","iopub.execute_input":"2023-08-11T12:21:41.607437Z","iopub.status.idle":"2023-08-11T12:21:42.122898Z","shell.execute_reply.started":"2023-08-11T12:21:41.607396Z","shell.execute_reply":"2023-08-11T12:21:42.122006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Polygons-annotation 🎯</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"****\n![](https://i.ibb.co/z4BQ2jH/Screenshot-from-2023-06-11-15-19-16.png)","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\nPolygonal segmentation masks in JSONL format, available for Dataset 1 and Dataset 2. Each line gives JSON annotations for a single image with:<ul>\n<li><code>id</code> Identifies the corresponding image in <strong>train/</strong></li>\n<li><code>annotations</code>  A list of mask annotations with:</li>\n<li><code>type</code> Identifies the type of structure annotated:<ul>\n<li><code>blood_vessel</code> The target structure. Your goal in this competition is to predict these kinds of masks on the test set.</li>\n<li><code>glomerulus</code> A capillary ball structure in the kidney. These parts of the images were excluded from blood vessel annotation. You should ensure none of your test set predictions occur within glomerulus structures as they will be counted as false positives. Annotations are provided for test set tiles.</li>\n<li><code>unsure</code> A structure the expert annotators cannot confidently distinguish as a blood vessel.</li></ul></li>\n<li><code>coordinates</code> A list of polygon coordinates defining the segmentation mask.</li></ul></li>\n</div>\n\n****","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Setup Pipeline ⚙️</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <br>pycocotools to encode masks and their subsequent evaluation.<br>\n    Set a random number generator for all frameworks.\n</div>","metadata":{}},{"cell_type":"code","source":"import torch\nfrom torch import nn\nimport random\n\nimport shutil\nimport os\nimport sys\nfrom colorama import Fore","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:45.235514Z","iopub.execute_input":"2023-08-11T12:21:45.236233Z","iopub.status.idle":"2023-08-11T12:21:49.058390Z","shell.execute_reply.started":"2023-08-11T12:21:45.236194Z","shell.execute_reply":"2023-08-11T12:21:49.057030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Class SetupPipline has three methods:\n\n - __pycocotools(): This method is a static method, which means that it can be called without creating an instance of the class. This method is used to install the PyCocoTools library, which is a Python library for working with COCO datasets.\n - seed_everything(): This method is also a static method. It is used to set the random seed for various Python libraries, such as NumPy, PyTorch, and CuDNN. This helps to ensure that the results of the code are reproducible.\n - __call__(): This is the main method of the SetupPipline class. It is called when an instance of the class is created. This method takes two arguments: seed and pycoco. The seed argument is the random seed to use, and the pycoco argument is a boolean value that indicates whether to install the PyCocoTools library.\n \n \n ### Details\n-  __pycocotools(): This method first checks if the /kaggle/working/packages directory exists. If it does not exist, the method creates it. The method then copies the pycocotools directory from the /kaggle/input/hubmap-tools-ultralytics-and-pycocotools directory to the /kaggle/working/packages directory. The method then changes the working directory to the /kaggle/working/packages/pycocotools-2.0.6 directory and runs the following commands:\n   - python setup.py install\n   - pip install . --no-index --find-links /kaggle/working/packages/ The first command installs the PyCocoTools library from the source code. The second command installs the PyCocoTools library from the /kaggle/working/packages directory.\n- seed_everything(): This method sets the random seed for the following Python libraries:\n  - random\n  - np.random\n  - torch.manual_seed\n  - torch.cuda.manual_seed\n  - torch.backends.cudnn.deterministic The random seed is set to the value of the seed argument.\n- __call__(): This method takes two arguments: seed and pycoco. The seed argument is the random seed to use, and the pycoco argument is a boolean value that indicates whether to install the PyCocoTools library.\n= If the pycoco argument is True, the __pycocotools() method is called to install the PyCocoTools library. If the seed argument is not None, the seed_everything() method is called to set the random seed.","metadata":{}},{"cell_type":"code","source":"class SetupPipline:   \n    @staticmethod\n    def __pycocotools() -> None:\n        if not os.path.exists(\"/kaggle/working/packages\"):\n            shutil.copytree(\"/kaggle/input/hubmap-tools-ultralytics-and-pycocotools/pycocotools/pycocotools\", \"/kaggle/working/packages\")\n            os.chdir(\"/kaggle/working/packages/pycocotools-2.0.6/\")\n            os.system(\"python setup.py install\")\n            os.system(\"pip install . --no-index --find-links /kaggle/working/packages/\")\n            os.chdir(\"/kaggle/working\")\n\n    @staticmethod\n    def seed_everything(seed: int) -> None:\n        random.seed(seed)\n        np.random.seed(seed)\n        torch.manual_seed(seed)\n        torch.cuda.manual_seed(seed)\n        torch.backends.cudnn.deterministic = True\n    \n    def __call__(self, seed: int = 42, pycoco: bool = True) -> None:\n        if pycoco:\n            self.__pycocotools()\n        if seed:\n            self.seed_everything(seed)","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:21:49.061384Z","iopub.execute_input":"2023-08-11T12:21:49.062428Z","iopub.status.idle":"2023-08-11T12:21:49.073027Z","shell.execute_reply.started":"2023-08-11T12:21:49.062374Z","shell.execute_reply":"2023-08-11T12:21:49.071895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%capture\nsetup = SetupPipline()\nSEED: int = 42\nsetup(seed=SEED, pycoco=True)","metadata":{"_kg_hide-input":false,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-08-11T12:21:53.976310Z","iopub.execute_input":"2023-08-11T12:21:53.976779Z","iopub.status.idle":"2023-08-11T12:22:57.156922Z","shell.execute_reply.started":"2023-08-11T12:21:53.976745Z","shell.execute_reply":"2023-08-11T12:22:57.155554Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Dataset libraries</b>\n</div>","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import Dataset\nimport cv2\nimport yaml\nimport json\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:11.513992Z","iopub.execute_input":"2023-08-11T12:23:11.514463Z","iopub.status.idle":"2023-08-11T12:23:11.720591Z","shell.execute_reply.started":"2023-08-11T12:23:11.514429Z","shell.execute_reply":"2023-08-11T12:23:11.719338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Dataset config</b>\n</div>","metadata":{}},{"cell_type":"code","source":"dataset_config = {\n    \"background\": {\n        \"apply_mask\": None,\n        \"label\": 0,\n        \"rgb\": (0, 0, 0),\n        \"loss_weight\": None\n    },\n    \"blood_vessel\": {\n        \"apply_mask\": True,\n        \"label\": 1,\n        \"rgb\": (255, 8, 8),\n        \"loss_weight\": None\n    },\n    \"glomerulus\": {\n        \"apply_mask\": True,\n        \"label\": 2,\n        \"rgb\": (8, 12, 255),\n        \"loss_weight\": None\n    },\n    \"unsure\": {\n        \"apply_mask\": True,\n        \"label\": 3,\n        \"rgb\": (8, 255, 20),\n        \"loss_weight\": None\n    }\n}","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:14.187255Z","iopub.execute_input":"2023-08-11T12:23:14.187762Z","iopub.status.idle":"2023-08-11T12:23:14.196798Z","shell.execute_reply.started":"2023-08-11T12:23:14.187727Z","shell.execute_reply":"2023-08-11T12:23:14.195247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- write_config function takes two arguments: data and path. The data argument is a dictionary of dictionaries. The path argument is the path to the file to write the configuration to.\n- The write_config function first opens the file at the specified path in write mode. Then, it uses the yaml.safe_dump() function to write the configuration data to the file. The yaml.safe_dump() function takes two arguments:\n  - stream: The file object to write the data to.\n  - data: The data to write to the file.\n  \n- yaml.safe_dump() function will try to pretty-print the configuration data, but it will not if the data contains any non-UTF8 characters.","metadata":{}},{"cell_type":"code","source":"def write_config(data: dict[dict, ...], path: str) -> None:\n    with open(path, mode=\"w\") as f:\n        yaml.safe_dump(stream=f, data=data)\n        \nwrite_config(dataset_config, __DATASET_CONFIG_PATH)","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:17.034769Z","iopub.execute_input":"2023-08-11T12:23:17.035848Z","iopub.status.idle":"2023-08-11T12:23:17.045708Z","shell.execute_reply.started":"2023-08-11T12:23:17.035810Z","shell.execute_reply":"2023-08-11T12:23:17.044111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Dataset 🪢</b>\n</div>","metadata":{}},{"cell_type":"markdown","source":"### HuBMAPDataset class has following methods:\n\n- __init__(): This method is the constructor of the class. It takes three arguments: annotation_path, image_path, and config_path. The annotation_path argument is the path to the file containing the annotations for the dataset. The image_path argument is the path to the directory containing the images for the dataset. The config_path argument is the path to the file containing the configuration for the dataset.\n- __len__(): This method returns the length of the dataset.\n- __getitem__(idx): This method returns the idxth sample from the dataset. The sample is a tuple of two elements: the image and the mask. The image is a NumPy array of shape (512, 512, 3). The mask is a NumPy array of shape (512, 512, 1).\n\n- HuBMAPDataset class first parses the annotations file to get a list of samples. Each sample is a dictionary that contains the following keys:\n    - id: The ID of the sample.\n    - annotations: A list of annotations for the sample.\n    \n- HuBMAPDataset loads the image and mask for each sample. The image is loaded from the file system and converted to a NumPy array. The mask is created by filling a NumPy array with zeros. For each annotation in the sample, the coordinates of the annotation are used to fill the mask with the color specified in the configuration file.Finally, the HuBMAPDataset class returns a tuple of the image and the mask.","metadata":{}},{"cell_type":"code","source":"class HuBMAPDataset(Dataset):\n    def __init__(self, \n                 annotation_path: str,\n                 image_path: str, \n                 config_path: str):\n        self.__image_path = image_path\n        self.__samples = self.parse_jsonl(annotation_path)\n        self.__config = self.load_config(config_path)\n    \n    def __len__(self) -> int:\n        return len(self.__samples)\n\n    def __getitem__(self, idx: int) -> tuple[np.ndarray, np.ndarray]:\n        image = self.__get_image(idx)\n        mask = self.__get_mask(idx)\n        # image = torch.tensor(image, dtype=torch.float32).permute(2, 0, 1)\n        # mask = torch.tensor(mask, dtype=torch.float32) \n        return image, mask\n        \n    @staticmethod\n    def parse_jsonl(path: str) -> list[dict, ...]:\n        with open(path, 'r') as json_file:\n            jsonl_labels = [\n                json.loads(line)\n                for line in notebook.tqdm(\n                    json_file, desc=\"Processing polygons\", total=1633\n                )\n            ]\n        return jsonl_labels\n\n    @staticmethod\n    def load_config(path: str) -> dict:\n        with open(path, mode=\"r\") as f:\n            data = yaml.load(stream=f, Loader=yaml.SafeLoader)\n        return data\n    \n    def __get_image_path(self, id: str) -> str:\n        path = os.path.join(\n            self.__image_path, f\"{id}.tif\"\n        )\n        return path\n    \n    def __get_image(self, idx: int) -> np.ndarray:\n        id = self.__samples[idx][\"id\"]\n        image_path = self.__get_image_path(id)\n        image = Image.open(image_path)\n        image = np.asarray(image)\n        return image\n            \n    def __get_mask(self, idx: int) -> np.ndarray:\n        mask = np.zeros((512, 512), dtype=np.uint8)\n        annotations = self.__samples[idx][\"annotations\"]\n        \n        for vessel in annotations:\n            vessel_type = vessel[\"type\"] \n            config = self.__config[vessel_type]\n            \n            if config[\"apply_mask\"]:\n                coordinates = np.array(vessel[\"coordinates\"])\n                mask = cv2.fillPoly(\n                    mask, pts=coordinates,\n                    color=config[\"rgb\"]\n                )\n        return mask","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:21.147021Z","iopub.execute_input":"2023-08-11T12:23:21.148519Z","iopub.status.idle":"2023-08-11T12:23:21.163643Z","shell.execute_reply.started":"2023-08-11T12:23:21.148470Z","shell.execute_reply":"2023-08-11T12:23:21.162811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Let's check dataset</b>\n</div>","metadata":{}},{"cell_type":"code","source":"dataset = HuBMAPDataset(__ANNOTATION_PATH, __TRAIN_PATH, __DATASET_CONFIG_PATH)","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:24.174804Z","iopub.execute_input":"2023-08-11T12:23:24.175806Z","iopub.status.idle":"2023-08-11T12:23:30.892575Z","shell.execute_reply.started":"2023-08-11T12:23:24.175760Z","shell.execute_reply":"2023-08-11T12:23:30.891370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image, mask = dataset[0]\n\nfig, (ax1, ax2) = plt.subplots(1, 2)\n\nax1.imshow(image)\nax2.imshow(mask)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:37.495762Z","iopub.execute_input":"2023-08-11T12:23:37.496213Z","iopub.status.idle":"2023-08-11T12:23:38.054738Z","shell.execute_reply.started":"2023-08-11T12:23:37.496180Z","shell.execute_reply":"2023-08-11T12:23:38.053553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Submission 💌</b>\n</div>\n\n<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <b>id, height, width, prediction_string</b>\n    <ul style=\"font-size:20px; font-family:verdana; line-height: 1.7em\">\n        <li>id - identifier of the image that came to the input of the neural network.</li>\n        <li>height - image height (constant value equal to 512).</li> \n        <li>width - image width (constant value equal to 512).</li> \n        <li>prediction_string:\n            <ul style=\"font-size:20px; font-family:verdana; line-height: 1.7em\">\n                <li>label - label class constant value equal to 0 (at least as I understand it, correct me if I'm wrong)</li>\n                <li>confidence - the confidence of the model that this object or instance belongs to the target class. That is, your model will give a mask at the output, where each mask will have the probability that this particular mask belongs to the desired class. It's like the probability of a model belonging to an object to a class. In fact, this is a probabilistic membership score that always appears when it comes to classification.</li>  \n            </ul>\n        </li> \n    </ul>\n</div>\n\n","metadata":{}},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #f0c7c7; font-family:verdana; color: #a63c3c; border: 2px #a63c3c solid\">\n    <b>Important 🙃</b>\n    <br>I removed the full implementation so that you understand that you must override the forward method, since I do not know what exactly your neural network returns and this could lead to confusion. In general, the class turned out to be quite comfortable. You only need to pass the model and the path to the test directory, and then call the submit() method. Please let me know if something doesn't work!<br>\n</div>","metadata":{}},{"cell_type":"code","source":"import base64\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom pycocotools import _mask as coco_mask\nimport typing as t\nimport zlib\nimport pandas as pd\nimport torchvision.transforms as T","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:43.644965Z","iopub.execute_input":"2023-08-11T12:23:43.645410Z","iopub.status.idle":"2023-08-11T12:23:43.934573Z","shell.execute_reply.started":"2023-08-11T12:23:43.645379Z","shell.execute_reply":"2023-08-11T12:23:43.933366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EncodeBinaryMask class has the following methods:\n\n- __checking_mask(): This method checks if the mask is a binary mask. If the mask is not a binary mask, the method raises an error.\n- __convert_mask(): This method converts the mask to a format that can be encoded by the coco_mask library.\n- __compress_encode(): This method compresses the encoded mask and encodes it in base64 format.\n- __call__(): This is the main method of the class. It takes one argument: mask. The mask argument is the binary mask to encode.\n\n- __call__() method first checks the mask to make sure it is a binary mask. If the mask is not a binary mask, the method raises an error.\n\n-  __call__() method then converts the mask to a format that can be encoded by the coco_mask library. The coco_mask library is a Python library for working with masks in the COCO format.\n\n- __call__() method then encodes the mask and compresses it in base64 format. The base64 format is a standard way to encode binary data in a text format.\n\n- __call__() method finally returns the base64 encoded mask.","metadata":{}},{"cell_type":"code","source":"class EncodeBinaryMask:\n    @staticmethod\n    def __checking_mask(mask: np.ndarray) -> np.ndarray:\n        if mask.dtype != np.bool:\n            raise ValueError(\n                \"expects a binary mask, received dtype == %s\" %\n                mask.dtype\n            )\n        return mask\n\n    @staticmethod\n    def __convert_mask(mask: np.ndarray):\n        mask_to_encode = mask.astype(np.uint8)\n        mask_to_encode = np.asfortranarray(mask_to_encode)\n        return mask_to_encode\n\n    @staticmethod\n    def __compress_encode(encoded_mask) -> t.Text:\n        binary_str = zlib.compress(encoded_mask, zlib.Z_BEST_COMPRESSION)\n        base64_str = base64.b64encode(binary_str)\n        return base64_str\n\n    def __call__(self, mask: np.ndarray) -> t.Text:\n        mask = self.__checking_mask(mask)\n        mask_to_encode = self.__convert_mask(mask)\n        encoded_mask = coco_mask.encode(mask_to_encode)[0][\"counts\"]\n        base64_str = self.__compress_encode(encoded_mask)\n        return base64_str\n","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:23:51.406006Z","iopub.execute_input":"2023-08-11T12:23:51.407098Z","iopub.status.idle":"2023-08-11T12:23:51.417073Z","shell.execute_reply.started":"2023-08-11T12:23:51.407058Z","shell.execute_reply":"2023-08-11T12:23:51.415823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Submission:\n    def __init__(self, dirpath: str, model: torch.nn.Module):\n        self.__eval_transforms = self.get_transforms()\n        self.__model = model\n        self.__encoder = EncodeBinaryMask()\n        self.__dirpath = dirpath\n        self.__filenames = os.listdir(dirpath)\n        self.conv1 = nn.Conv2d(3,512,512)\n        self.pool = nn.MaxPool2d(1, 1)\n        self.conv2 = nn.Conv2d(3,512,512)\n        self.fc = nn.Linear(512,10)\n        \n        self.__submission_dict = {\n            \"id\": [],\n            \"height\": [],\n            \"width\": [],\n            \"prediction_string\": []\n        }\n        \n        self.submission = None\n    \n    @staticmethod\n    def get_transforms():\n        return T.Compose([\n            T.ToTensor(),\n            T.Resize(size=(512, 512)),\n            T.Normalize(mean=[0.485, 0.456, 0.406],\n                        std=[0.229, 0.224, 0.225])\n        ])\n\n    def __len__(self):\n        return len(self.__filenames)\n\n    def __get_columns(self) -> None:\n        for filename in self.__filenames:\n            path = self.__get_image_path(filename)\n            image = self.__get_image(path)\n            masks = self.__forward(image)\n            identifier, height, width, prediction_string = self.__get_cells(filename, masks)\n            self.__update_columns(identifier, height, width, prediction_string)\n\n    def __update_columns(self, identifier: str, height: int, width: int, prediction_string: str) -> None:\n        self.__submission_dict[\"id\"].append(identifier)\n        self.__submission_dict[\"height\"].append(height)\n        self.__submission_dict[\"width\"].append(width)\n        self.__submission_dict[\"prediction_string\"].append(prediction_string)\n\n    def __get_cells(self, filename: str, masks: list):\n        prediction_string = \"\"\n        prediction_string = self.__get_prediction_string(masks, prediction_string)\n        identifier = filename.split(\".\")[0]\n        height, width = mask.shape\n        return identifier, height, width, prediction_string\n\n    def __get_prediction_string(self, masks: list, prediction_string: str) -> str:\n        \"\"\"\n        If the neural network did not find the target structure,\n        then we will return an empty prediction_string.\n        \n        However, the columns:\n            id, height, width - must be present for all test images!!!\n        \"\"\"\n        \n        if masks:\n            for outputs in masks:\n                mask = outputs[\"mask\"].detach().permute(1,2,0).cpu().numpy()\n                mask = np.where(mask > 0.5, 1, 0).astype(np.bool)\n                base64_str = self.__encoder(mask)\n                confidence = outputs[\"confidence\"]\n                prediction_string += f\"0 {confidence} {base64_str.decode('utf-8')} \"\n        return prediction_string\n\n    def __get_image_path(self, filename: str) -> str:\n        return os.path.join(\n            self.__dirpath, filename\n        )\n\n    def __get_image(self, path: str) -> torch.Tensor:\n        image = Image.open(path)\n        image = np.asarray(image)\n        image = self.__eval_transforms(image)\n        return image\n\n    # You must implement this function to work with your custom neural network!\n    def __forward(self, image: torch.tensor) ->list:\n        \"\"\"\n        This fuction should return list with masks & confidence.\n        And each mask we shoulde encode (see EncodeBinaryMask & sample_submission file) \n        \n        outputs <- model(image) \n        outputs -> [\n                    {\"mask\": mask1, \"confidence\": confidence1},\n                    {\"mask\": mask2, \"confidence\": confidence2}, \n                    ...,\n                    {\"mask\": maskN, \"confidence\": confidenceN}\n                   ]\n                                  \n        Example:\n        \"\"\"\n        masks = self.__model(image) # Mask must have shape 1x512x512\n        masks = torch.relu(image)\n        masks= self.pool(nn.functional.relu(self.conv1(image)))\n        masks = self.pool(nn.functional.relu(self.conv2(image)))\n        masks = torch.flatten(image)\n        masks = torch.relu(image)\n        masks = torch.log_softmax(image,dim=0)\n        masks = nn.functional.log_softmax(self.fc(image),dim=1)\n        mask1 = torch.nn.Flatten(0, 1)\n        masks = torch.nn.Flatten(mask1(image))\n        masks = torch.nn.Flatten(0, 1)\n#         masks = torch.sum(image)\n        masks = self.__model(image) * 5\n        return masks \n\n    def submit(self) -> None:\n        if not self.submission:\n            self.__get_columns()\n            self.submission = pd.DataFrame(self.__submission_dict)\n            self.submission = self.submission.set_index('id')\n            self.submission.to_csv(\"submission.csv\")\n","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:58:16.033294Z","iopub.execute_input":"2023-08-11T12:58:16.033703Z","iopub.status.idle":"2023-08-11T12:58:16.062110Z","shell.execute_reply.started":"2023-08-11T12:58:16.033658Z","shell.execute_reply":"2023-08-11T12:58:16.060710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div class=\"alert alert-block alert-info\" style=\"font-size:20px; background-color: #ffa3a3; font-family:verdana; color: #8a0f0f; border: 2px #ff0303 solid\">\n    <b>Sample model</b>\n</div>","metadata":{}},{"cell_type":"code","source":"class MyBestModel:\n    @staticmethod\n    def generate_masks(num_masks: int) -> list[dict, ...]:\n        masks = []\n        for _ in range(num_masks):\n            mask = torch.randint(0, 2, (1, 512, 512))\n            confidence = round(float(torch.rand(1)[0]), 2)\n            masks.append({\"mask\": mask, \"confidence\": confidence})\n        return masks\n        \n    def __call__(self, image) -> list[dict, ...]:\n        num_masks = torch.randint(1, 5, (1, 1))\n        masks = self.generate_masks(num_masks)\n        return masks","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:56:31.810308Z","iopub.execute_input":"2023-08-11T12:56:31.811607Z","iopub.status.idle":"2023-08-11T12:56:31.820229Z","shell.execute_reply.started":"2023-08-11T12:56:31.811542Z","shell.execute_reply":"2023-08-11T12:56:31.818686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = MyBestModel()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:56:35.479134Z","iopub.execute_input":"2023-08-11T12:56:35.479521Z","iopub.status.idle":"2023-08-11T12:56:35.486396Z","shell.execute_reply.started":"2023-08-11T12:56:35.479493Z","shell.execute_reply":"2023-08-11T12:56:35.485293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = Submission(dirpath=__TEST_PATH, model=model)\nsub.submit()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:56:37.480284Z","iopub.execute_input":"2023-08-11T12:56:37.481312Z","iopub.status.idle":"2023-08-11T12:56:49.986753Z","shell.execute_reply.started":"2023-08-11T12:56:37.481263Z","shell.execute_reply":"2023-08-11T12:56:49.984896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.submission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-11T12:45:38.284487Z","iopub.execute_input":"2023-08-11T12:45:38.284968Z","iopub.status.idle":"2023-08-11T12:45:38.301999Z","shell.execute_reply.started":"2023-08-11T12:45:38.284934Z","shell.execute_reply":"2023-08-11T12:45:38.300611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}