{"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":"# How to make a submission using the Run-Length Encoding format","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\n\nfrom pathlib import Path\ndata_path = Path('/kaggle/input/google-research-identify-contrails-reduce-global-warming')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-08-09T00:35:58.402754Z","iopub.execute_input":"2023-08-09T00:35:58.403554Z","iopub.status.idle":"2023-08-09T00:35:58.431667Z","shell.execute_reply.started":"2023-08-09T00:35:58.403506Z","shell.execute_reply":"2023-08-09T00:35:58.430589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Run-Length Code\n\nThe following is code to both encode and decode RLE format.\n\nIMPORTANT: Unlike many previous Kaggle competition, empty predictions must be encoded as `'-'`. Empty string / null predictions will cause an error in scoring. The code below handles this change.","metadata":{}},{"cell_type":"code","source":"def rle_encode(x, fg_val=1):\n    \"\"\"\n    Args:\n        x:  numpy array of shape (height, width), 1 - mask, 0 - background\n    Returns: run length encoding as list\n    \"\"\"\n\n    dots = np.where(\n        x.T.flatten() == fg_val)[0]  # .T sets Fortran order down-then-right\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if b > prev + 1:\n            run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return run_lengths\n\n\ndef list_to_string(x):\n    \"\"\"\n    Converts list to a string representation\n    Empty list returns '-'\n    \"\"\"\n    if x: # non-empty list\n        s = str(x).replace(\"[\", \"\").replace(\"]\", \"\").replace(\",\", \"\")\n    else:\n        s = '-'\n    return s\n\n\ndef rle_decode(mask_rle, shape=(256, 256)):\n    '''\n    mask_rle: run-length as string formatted (start length)\n              empty predictions need to be encoded with '-'\n    shape: (height, width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    if mask_rle != '-': \n        s = mask_rle.split()\n        starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n        starts -= 1\n        ends = starts + lengths\n        for lo, hi in zip(starts, ends):\n            img[lo:hi] = 1\n    return img.reshape(shape, order='F')  # Needed to align to RLE direction","metadata":{"execution":{"iopub.status.busy":"2023-08-09T00:35:58.454467Z","iopub.execute_input":"2023-08-09T00:35:58.454918Z","iopub.status.idle":"2023-08-09T00:35:58.468359Z","shell.execute_reply.started":"2023-08-09T00:35:58.454874Z","shell.execute_reply":"2023-08-09T00:35:58.466508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create a naive submission\n\nWe'll use just `band_08` and predict that the 1000 pixels with the highest numerical values are contrails.","metadata":{}},{"cell_type":"code","source":"test_recs = os.listdir(data_path / 'test')\nprint(test_recs)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T00:35:58.471817Z","iopub.execute_input":"2023-08-09T00:35:58.472969Z","iopub.status.idle":"2023-08-09T00:35:58.489707Z","shell.execute_reply.started":"2023-08-09T00:35:58.472906Z","shell.execute_reply":"2023-08-09T00:35:58.488342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n = 1000\nband_08 = np.load(data_path / 'test' / test_recs[0] / 'band_08.npy').sum(axis=2)\n# https://stackoverflow.com/a/57105712\npreds = np.c_[np.unravel_index(np.argpartition(band_08.ravel(),-n)[-n:],band_08.shape)]\nmask = np.zeros((256, 266))\nmask[preds[:, 0], preds[:, 1]] = 1\n\nplt.imshow(mask, cmap='Greys')\nplt.title(\"Obviously Not Contrails\", fontsize='16')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-09T00:35:58.491143Z","iopub.execute_input":"2023-08-09T00:35:58.491852Z","iopub.status.idle":"2023-08-09T00:35:58.819467Z","shell.execute_reply.started":"2023-08-09T00:35:58.491811Z","shell.execute_reply":"2023-08-09T00:35:58.818238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Convert to RLE","metadata":{}},{"cell_type":"code","source":"list_to_string(rle_encode(mask))","metadata":{"execution":{"iopub.status.busy":"2023-08-09T00:35:58.820914Z","iopub.execute_input":"2023-08-09T00:35:58.821283Z","iopub.status.idle":"2023-08-09T00:35:58.829008Z","shell.execute_reply.started":"2023-08-09T00:35:58.821246Z","shell.execute_reply":"2023-08-09T00:35:58.827852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Now let's automate a submission","metadata":{}},{"cell_type":"code","source":"submission = pd.read_csv(data_path / 'sample_submission.csv', index_col='record_id')\n\nfor rec in test_recs:\n    band_08 = np.load(data_path / 'test' / rec / 'band_08.npy').sum(axis=2)\n    preds = np.c_[np.unravel_index(np.argpartition(band_08.ravel(),-n)[-n:],band_08.shape)]\n    mask = np.zeros((256, 266))\n    mask[preds[:, 0], preds[:, 1]] = 1\n    # notice the we're converting rec to an `int` here:\n    submission.loc[int(rec), 'encoded_pixels'] = list_to_string(rle_encode(mask))\n\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-09T00:35:58.831536Z","iopub.execute_input":"2023-08-09T00:35:58.831889Z","iopub.status.idle":"2023-08-09T00:35:58.968457Z","shell.execute_reply.started":"2023-08-09T00:35:58.831854Z","shell.execute_reply":"2023-08-09T00:35:58.96737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2023-08-09T00:35:58.970009Z","iopub.execute_input":"2023-08-09T00:35:58.970364Z","iopub.status.idle":"2023-08-09T00:35:58.980566Z","shell.execute_reply.started":"2023-08-09T00:35:58.970331Z","shell.execute_reply":"2023-08-09T00:35:58.979175Z"},"trusted":true},"execution_count":null,"outputs":[]}]}