{"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":"code","source":"import os\nimport numpy as np\nfrom matplotlib.animation import FuncAnimation\nimport matplotlib.pyplot as plt\nfrom IPython.display import HTML\n\n# CONSTANTS\n_N_TIMES_BEFORE = 4\n_BOUNDS = {\n    'band_11': (243, 303),\n    'band_14': (-4, 2),\n    'band_15': (-4, 5)\n}\n_BANDS = ['band_11', 'band_14', 'band_15', 'human_pixel_masks', 'human_individual_masks']\n\ndef print_debug(*args):\n    print(\"[DEBUG]\", *args)\n\ndef load_band(base_dir, record_id, band):\n    print_debug(f\"Loading numpy array for band: {band}\")\n    band_path = os.path.join(base_dir, record_id, f'{band}.npy')\n    with open(band_path, 'rb') as f:\n        band_data = np.load(f)\n    print_debug(f\"Loaded band: {band} with shape {band_data.shape}\")\n    return band_data\n\ndef normalize_band(band_data, bounds):\n    print_debug(f\"Normalizing band data with bounds: {bounds}\")\n    normalized_data = (band_data - bounds[0]) / (bounds[1] - bounds[0])\n    return normalized_data\n\ndef display_image(img, mask, individual_masks):\n    print_debug(\"Displaying image.\")\n    plt.figure(figsize=(18, 6))\n\n    ax = plt.subplot(1, 3, 1)\n    ax.imshow(img)\n    ax.set_title('Band Image')\n\n    ax = plt.subplot(1, 3, 2)\n    ax.imshow(mask, interpolation='none')\n    ax.set_title('Mask')\n\n    ax = plt.subplot(1, 3, 3)\n    ax.imshow(img)\n    ax.imshow(mask, cmap='Reds', alpha=.4, interpolation='none')\n    ax.set_title('Image with Mask Overlay')\n\n    n = individual_masks.shape[-1]\n    plt.figure(figsize=(16, 4))\n    for i in range(n):\n        plt.subplot(1, n, i+1)\n        plt.imshow(individual_masks[..., i], interpolation='none')\n        plt.title(f'Individual Mask {i+1}')\n\ndef animate_image(img, mask):\n    print_debug(\"Animating image.\")\n    fig, ax = plt.subplots(figsize=(6, 6))\n    im = ax.imshow(img[..., 0], cmap='gray')\n    overlay = ax.imshow(mask[..., 0], cmap='jet', alpha=0.5)  # Overlay the mask with transparency\n\n    ax.set_title('False Color Band Animation Over Time')\n    ax.set_xlabel('Spacial dim: X Coordinate')\n    ax.set_ylabel('Spacial dim: Y Coordinate')\n\n    def draw(i):\n        im.set_array(img[..., i])\n        overlay.set_array(mask[..., i])\n        return [im, overlay]\n\n    anim = FuncAnimation(\n        fig, draw, frames=img.shape[-1], interval=500, blit=True\n    )\n\n    plt.close(fig)\n    return anim\n\ndef calculate_contrail_proportions(mask):\n    proportions = np.mean(mask, axis=(0, 1))\n    plt.plot(proportions)\n    plt.title('Proportion of Pixels Labeled as Contrails Over Time')\n    plt.xlabel('Time')\n    plt.ylabel('Proportion')\n    plt.show()\n\ndef calculate_dice_coefficient(y_true, y_pred):\n    intersection = np.sum(y_true * y_pred)\n    return (2. * intersection + 1.) / (np.sum(y_true) + np.sum(y_pred) + 1.)\n\ndef main(base_dir, record_id):\n    print_debug(f\"Running main function with base_dir={base_dir} and record_id={record_id}\")\n\n    # Load band data (from the first version for clarity)\n    band11 = load_band(base_dir, record_id, 'band_11')\n    band14 = load_band(base_dir, record_id, 'band_14')\n    band15 = load_band(base_dir, record_id, 'band_15')\n    human_pixel_mask = load_band(base_dir, record_id, 'human_pixel_masks')\n    human_individual_mask = load_band(base_dir, record_id, 'human_individual_masks')\n\n    # Normalization and false color image generation (from the second version for efficiency)\n    r = normalize_band(band15 - band14, _TDIFF_BOUNDS)\n    g = normalize_band(band14 - band11, _CLOUD_TOP_TDIFF_BOUNDS)\n    b = normalize_band(band14, _T11_BOUNDS)\n    false_color = np.clip(np.stack([r, g, b], axis=2), 0, 1)\n\n    # Check if mask has the same number of frames as false_color and repeat if necessary (enhancement)\n    num_frames = false_color.shape[-1]\n    if human_pixel_mask.shape[-1] == 1:\n        human_pixel_mask = np.repeat(human_pixel_mask, num_frames, axis=-1)\n\n    # Extract a single frame from the mask for display\n    displayed_mask = human_pixel_mask[..., _N_TIMES_BEFORE]\n\n    # Call the display and animation functions\n    display_image(false_color[..., _N_TIMES_BEFORE], displayed_mask, human_individual_mask)\n    animation = animate_image(false_color, human_pixel_mask)\n    calculate_contrail_proportions(human_pixel_mask)\n\n    # Calculate Dice coefficient on validation set (commented out since we don't have a model prediction)\n    # y_pred = model.predict(band_data)  \n    # y_true = human_pixel_mask.flatten()\n    # dice_coeff = calculate_dice_coefficient(y_true, y_pred)\n    # print(f'Dice coefficient on validation set: {dice_coeff}')\n\n    return animation\n\n# Call the main function with the base directory and record id as arguments\nbase_dir = '/kaggle/input/google-research-identify-contrails-reduce-global-warming/train'\nrecord_id = '1704010292581573769'\nanimation = main(base_dir, record_id)\n\n# Display the animation in the notebook\nHTML(animation.to_jshtml())","metadata":{"execution":{"iopub.status.busy":"2023-07-25T01:42:54.746666Z","iopub.execute_input":"2023-07-25T01:42:54.74708Z","iopub.status.idle":"2023-07-25T01:43:00.011805Z","shell.execute_reply.started":"2023-07-25T01:42:54.747049Z","shell.execute_reply":"2023-07-25T01:43:00.010161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Mask Overlay in Animations Seeks to Offer:\n- **Immediate Validation:** Directly compare mask with actual imagery.\n- **Clear Contrail Tracking:** Easily observe when and where human mask detects contrails and its subsequent trajectory shifts.\n- **Temporal Dynamics:** Highlights contrail evolution over frames.\n- **Debugging Aid:** Offers visual feedback on detection precision.\n\n# Previous Ash Color Animation (no mask overlay):","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nfrom matplotlib import animation\nimport matplotlib.pyplot as plt\nfrom IPython.display import HTML\n\n# CONSTANTS\n_N_TIMES_BEFORE = 4\n_T11_BOUNDS = (243, 303)\n_CLOUD_TOP_TDIFF_BOUNDS = (-4, 5)\n_TDIFF_BOUNDS = (-4, 2)\n_BANDS = ['band_11', 'band_14', 'band_15', 'human_pixel_masks', 'human_individual_masks']\n\ndef print_debug(*args):\n    # Prints debug messages\n    print(\"[DEBUG]\", *args)\n\ndef load_band(base_dir, record_id, band):\n    # Loads band data from file\n    print_debug(f\"Loading numpy array for band: {band}\")\n    band_path = os.path.join(base_dir, record_id, f'{band}.npy')\n    with open(band_path, 'rb') as f:\n        band_data = np.load(f)\n    print_debug(f\"Loaded band: {band} with shape {band_data.shape}\")\n    return band_data\n\ndef normalize_band(band_data, bounds):\n    # Normalizes band data using given bounds\n    print_debug(f\"Normalizing band data with bounds: {bounds}\")\n    normalized_data = (band_data - bounds[0]) / (bounds[1] - bounds[0])\n    print_debug(f\"Normalization complete. Data min: {normalized_data.min()}, max: {normalized_data.max()}\")\n    return normalized_data\n\ndef display_image(img, mask, individual_masks):\n    # Displays image and masks\n    print_debug(\"Displaying image.\")\n    plt.figure(figsize=(18, 6))\n\n    ax = plt.subplot(1, 3, 1)\n    ax.imshow(img)\n    ax.set_title('Band Image')\n\n    ax = plt.subplot(1, 3, 2)\n    ax.imshow(mask, interpolation='none')\n    ax.set_title('Mask')\n\n    ax = plt.subplot(1, 3, 3)\n    ax.imshow(img)\n    ax.imshow(mask, cmap='Reds', alpha=.4, interpolation='none')\n    ax.set_title('Image with Mask Overlay')\n\n    n = individual_masks.shape[-1]\n    plt.figure(figsize=(16, 4))\n    for i in range(n):\n        plt.subplot(1, n, i+1)\n        plt.imshow(individual_masks[..., i], interpolation='none')\n        plt.title(f'Individual Mask {i+1}')\n\ndef animate_image(img):\n    # Animates image using matplotlib\n    print_debug(\"Animating image.\")\n    fig = plt.figure(figsize=(6, 6))\n    im = plt.imshow(img[..., 0])\n\n    def draw(i):\n        im.set_array(img[..., i])\n        return [im]\n\n    anim = animation.FuncAnimation(\n        fig, draw, frames=img.shape[-1], interval=500, blit=True\n    )\n    \n    plt.close(fig)\n    print_debug(\"Animation created.\")\n    return HTML(anim.to_jshtml())\n\ndef main(base_dir, record_id):\n    # Main function to load and display data\n    print_debug(f\"Running main function with base_dir={base_dir} and record_id={record_id}\")\n    \n    band11 = load_band(base_dir, record_id, 'band_11')\n    band14 = load_band(base_dir, record_id, 'band_14')\n    band15 = load_band(base_dir, record_id, 'band_15')\n    human_pixel_mask = load_band(base_dir, record_id, 'human_pixel_masks')\n    human_individual_mask = load_band(base_dir, record_id, 'human_individual_masks')\n\n    r = normalize_band(band15 - band14, _TDIFF_BOUNDS)\n    g = normalize_band(band14 - band11, _CLOUD_TOP_TDIFF_BOUNDS)\n    b = normalize_band(band14,_T11_BOUNDS)\n\n    false_color = np.clip(np.stack([r,g,b], axis=2),0 ,1)\n\n    img=false_color[..., _N_TIMES_BEFORE]\n\n    display_image(img,human_pixel_mask,human_individual_mask)\n    return animate_image(false_color)\n\n# Call the main function with the base directory and record id as arguments\nanimation=main('/kaggle/input/google-research-identify-contrails-reduce-global-warming/train','1704010292581573769')\nanimation","metadata":{"execution":{"iopub.status.busy":"2023-07-25T01:43:00.014189Z","iopub.execute_input":"2023-07-25T01:43:00.014541Z","iopub.status.idle":"2023-07-25T01:43:04.796911Z","shell.execute_reply.started":"2023-07-25T01:43:00.014511Z","shell.execute_reply":"2023-07-25T01:43:04.795542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<h2 id=\"credit-goes-to-all-authors-and-contributors\">🥇 Credit goes to all authors and contributors ⤵︎ </h2>\n\n- This script is inspired by [INVERSION's notebook on Kaggle](https://www.kaggle.com/code/inversion/visualizing-contrails).\n- How to create the standard RGB images: [Compilation of RGB Recipes (i.e. Ash RGB)](https://eumetrain.org/sites/default/files/2020-05/RGB_recipes.pdf)\n- This script is inspired by [Google Research - Identify Contrails to Reduce Global Warming](https://www.kaggle.com/competitions/google-research-identify-contrails-reduce-global-warming)\n---\n## Appendix:\n- [GitHub: src/utils/contrail_animation](https://github.com/patmejia/contrails-vision/blob/main/src/utils/contrail_animation.py): execute the Python code locally.\n","metadata":{}},{"cell_type":"code","source":"from IPython.display import display, Markdown\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\n\ntext = \"\"\"\n## Appendix: Analysis of Atmospheric Absorptivity and Earth's Radiation Emission\n- Study of absorptivity in gases: O2, O3, N2O, CO2, H2O, CH4.\n- Examination of Earth's radiation emission.\n- Details on color channels, ash RGB range, and temperature range for IR10.8 and IR12.0 satellite imagery.\n\"\"\"\n\ndisplay(Markdown(text))\n\nimages = [\n    '/kaggle/input/contrail-vision-research-related-images-docs/atmospheric-gases-absorptivity.png',\n    '/kaggle/input/contrail-vision-research-related-images-docs/satellite-sensing-radiation.png',\n    '/kaggle/input/contrail-vision-research-related-images-docs/ash-rgb.png'\n]\n\nfor img_path in images:\n    img = mpimg.imread(img_path)\n    plt.figure(figsize=(10,10)) # you can adjust the size as per your requirement\n    plt.imshow(img)\n    plt.axis('off')\n    plt.show()","metadata":{"_kg_hide-input":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2023-07-25T01:43:04.798666Z","iopub.execute_input":"2023-07-25T01:43:04.799122Z","iopub.status.idle":"2023-07-25T01:43:06.055821Z","shell.execute_reply.started":"2023-07-25T01:43:04.799079Z","shell.execute_reply":"2023-07-25T01:43:06.054355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<div style=\"background-color: #f2f2f2; padding: 53px; border-radius: 5px;\">\n  <h3>If you found this notebook helpful...</h3>\n  <p>\n  Please consider giving it a star. Your support helps me continue to develop high-quality code and pursue my career as a data analyst/engineer. Feedback is always welcome and appreciated. Thank you for taking the time to read my work! \n  </p> \n  <h4>\n  <p style=\"text-align: right;\">\n  <a href=\"https://github.com/patmejia\"> - pat [¬º-°]¬ </a>\n  </h4>\n  </p>\n</div>","metadata":{}}]}