{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opengeos/solara-geemap/blob/main/notebooks/08_compare.ipynb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# %pip install -U geemap solara" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ee\n", "import geemap\n", "import ipywidgets as widgets\n", "import solara\n", "from datetime import date\n", "\n", "\n", "class Map(geemap.Map):\n", " def __init__(self, **kwargs):\n", " super().__init__(**kwargs)\n", " self.add_basemap(\"Esri.WorldImagery\")\n", " self.add_gui_widget(add_header=True)\n", "\n", " def clean_up(self):\n", "\n", " layers = [\n", " \"Pre-event Image\",\n", " \"Post-event Image\",\n", " \"Pre-event NDWI\",\n", " \"Post-event NDWI\",\n", " \"Pre-event Water\",\n", " \"Post-event Water\",\n", " \"Disappeared Water\",\n", " \"New Water\",\n", " ]\n", " for layer_name in layers:\n", " layer = self.find_layer(layer_name)\n", " if layer is not None:\n", " self.remove(layer)\n", "\n", " def add_gui_widget(self, position=\"topright\", **kwargs):\n", "\n", " widget = widgets.VBox(layout=widgets.Layout(padding=\"0px 5px 0px 5px\"))\n", " pre_widget = widgets.HBox()\n", " post_widget = widgets.HBox()\n", " layout = widgets.Layout(width=\"auto\")\n", " style = {\"description_width\": \"initial\"}\n", " padding = \"0px 5px 0px 5px\"\n", " pre_start_date = widgets.DatePicker(\n", " description=\"Start\",\n", " value=date(2014, 1, 1),\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"160px\"),\n", " )\n", " pre_end_date = widgets.DatePicker(\n", " description=\"End\",\n", " value=date(2014, 12, 31),\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"160px\"),\n", " )\n", " pre_cloud_cover = widgets.IntSlider(\n", " description=\"Cloud\",\n", " min=0,\n", " max=100,\n", " value=25,\n", " step=1,\n", " readout=False,\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"130px\"),\n", " )\n", " pre_cloud_label = widgets.Label(value=str(pre_cloud_cover.value))\n", " geemap.jslink_slider_label(pre_cloud_cover, pre_cloud_label)\n", " pre_widget.children = [\n", " pre_start_date,\n", " pre_end_date,\n", " pre_cloud_cover,\n", " pre_cloud_label,\n", " ]\n", " post_start_date = widgets.DatePicker(\n", " description=\"Start\",\n", " value=date(2024, 1, 1),\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"160px\"),\n", " )\n", " post_end_date = widgets.DatePicker(\n", " description=\"End\",\n", " value=date(2024, 12, 31),\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"160px\"),\n", " )\n", " post_cloud_cover = widgets.IntSlider(\n", " description=\"Cloud\",\n", " min=0,\n", " max=100,\n", " value=30,\n", " step=1,\n", " readout=False,\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"130px\"),\n", " )\n", " post_cloud_label = widgets.Label(value=str(post_cloud_cover.value))\n", " geemap.jslink_slider_label(post_cloud_cover, post_cloud_label)\n", " post_widget.children = [\n", " post_start_date,\n", " post_end_date,\n", " post_cloud_cover,\n", " post_cloud_label,\n", " ]\n", "\n", " apply_btn = widgets.Button(description=\"Apply\", layout=layout)\n", " reset_btn = widgets.Button(description=\"Reset\", layout=layout)\n", " buttons = widgets.HBox([apply_btn, reset_btn])\n", " output = widgets.Output()\n", "\n", " use_split = widgets.Checkbox(\n", " value=False,\n", " description=\"Split map\",\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"100px\"),\n", " )\n", "\n", " use_ndwi = widgets.Checkbox(\n", " value=False,\n", " description=\"Compute NDWI\",\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"160px\"),\n", " )\n", "\n", " ndwi_threhold = widgets.FloatSlider(\n", " description=\"Threshold\",\n", " min=-1,\n", " max=1,\n", " value=0,\n", " step=0.05,\n", " readout=True,\n", " style=style,\n", " layout=widgets.Layout(padding=padding, width=\"230px\"),\n", " )\n", "\n", " options = widgets.HBox(\n", " [\n", " use_split,\n", " use_ndwi,\n", " ndwi_threhold,\n", " ]\n", " )\n", "\n", " widget.children = [pre_widget, post_widget, options, buttons, output]\n", " self.add_widget(widget, position=position, **kwargs)\n", "\n", " def apply_btn_click(b):\n", "\n", " marker_layer = self.find_layer(\"Search location\")\n", " if marker_layer is not None:\n", " self.remove(marker_layer)\n", " self.clean_up()\n", "\n", " if self.user_roi is None:\n", " output.clear_output()\n", " output.append_stdout(\"Please draw a ROI first.\")\n", " elif (\n", " pre_start_date.value is None\n", " or pre_end_date.value is None\n", " or post_start_date.value is None\n", " or post_end_date.value is None\n", " ):\n", " output.clear_output()\n", " output.append_stdout(\"Please select start and end dates.\")\n", "\n", " elif self.user_roi is not None:\n", " output.clear_output()\n", " output.append_stdout(\"Computing... Please wait.\")\n", " roi = ee.FeatureCollection(self.user_roi)\n", " vis_params = {\"bands\": [\"B6\", \"B5\", \"B4\"], \"min\": 0, \"max\": 0.4}\n", " if pre_start_date.value.strftime(\"%Y-%m-%d\") < \"2013-04-11\":\n", " pre_col = geemap.landsat_timeseries(\n", " roi,\n", " start_year=pre_start_date.value.year,\n", " end_year=pre_end_date.value.year,\n", " ).select([\"SWIR1\", \"NIR\", \"Red\", \"Green\"], [\"B6\", \"B5\", \"B4\", \"B3\"])\n", " else:\n", " pre_col = (\n", " ee.ImageCollection(\"NASA/HLS/HLSL30/v002\")\n", " .filterBounds(roi)\n", " .filterDate(\n", " pre_start_date.value.strftime(\"%Y-%m-%d\"),\n", " pre_end_date.value.strftime(\"%Y-%m-%d\"),\n", " )\n", " .filter(ee.Filter.lt(\"CLOUD_COVERAGE\", pre_cloud_cover.value))\n", " )\n", "\n", " if post_start_date.value.strftime(\"%Y-%m-%d\") < \"2013-04-11\":\n", " post_col = geemap.landsat_timeseries(\n", " roi,\n", " start_year=post_start_date.value.year,\n", " end_year=post_end_date.value.year,\n", " ).select([\"SWIR1\", \"NIR\", \"Red\", \"Green\"], [\"B6\", \"B5\", \"B4\", \"B3\"])\n", " else:\n", " post_col = (\n", " ee.ImageCollection(\"NASA/HLS/HLSL30/v002\")\n", " .filterBounds(roi)\n", " .filterDate(\n", " post_start_date.value.strftime(\"%Y-%m-%d\"),\n", " post_end_date.value.strftime(\"%Y-%m-%d\"),\n", " )\n", " .filter(ee.Filter.lt(\"CLOUD_COVERAGE\", post_cloud_cover.value))\n", " )\n", "\n", " pre_img = pre_col.median().clip(roi)\n", " post_img = post_col.median().clip(roi)\n", "\n", " if use_split.value:\n", " left_layer = geemap.ee_tile_layer(\n", " pre_img, vis_params, \"Pre-event Image\"\n", " )\n", " right_layer = geemap.ee_tile_layer(\n", " post_img, vis_params, \"Post-event Image\"\n", " )\n", " self.split_map(\n", " left_layer,\n", " right_layer,\n", " add_close_button=True,\n", " left_label=\"Pre-event\",\n", " right_label=\"Post-event\",\n", " )\n", " else:\n", " pre_img = pre_col.median().clip(roi)\n", " post_img = post_col.median().clip(roi)\n", " self.add_layer(pre_img, vis_params, \"Pre-event Image\")\n", " self.add_layer(post_img, vis_params, \"Post-event Image\")\n", "\n", " if use_ndwi.value and (not use_split.value):\n", " pre_ndwi = pre_img.normalizedDifference([\"B3\", \"B6\"]).rename(\"NDWI\")\n", " post_ndwi = post_img.normalizedDifference([\"B3\", \"B6\"]).rename(\n", " \"NDWI\"\n", " )\n", " ndwi_vis = {\"min\": -1, \"max\": 1, \"palette\": \"ndwi\"}\n", " self.add_layer(pre_ndwi, ndwi_vis, \"Pre-event NDWI\", False)\n", " self.add_layer(post_ndwi, ndwi_vis, \"Post-event NDWI\", False)\n", "\n", " pre_water = pre_ndwi.gt(ndwi_threhold.value)\n", " post_water = post_ndwi.gt(ndwi_threhold.value)\n", " self.add_layer(\n", " pre_water.selfMask(), {\"palette\": \"blue\"}, \"Pre-event Water\"\n", " )\n", " self.add_layer(\n", " post_water.selfMask(), {\"palette\": \"red\"}, \"Post-event Water\"\n", " )\n", " new_water = post_water.subtract(pre_water).gt(0)\n", " disappear_water = pre_water.subtract(post_water).gt(0)\n", " self.add_layer(\n", " disappear_water.selfMask(),\n", " {\"palette\": \"brown\"},\n", " \"Disappeared Water\",\n", " )\n", " self.add_layer(\n", " new_water.selfMask(), {\"palette\": \"cyan\"}, \"New Water\"\n", " )\n", "\n", " with output:\n", " output.clear_output()\n", "\n", " output.clear_output()\n", "\n", " apply_btn.on_click(apply_btn_click)\n", "\n", " def reset_btn_click(b):\n", " self.clean_up()\n", " self._draw_control.clear()\n", " draw_layer = self.find_layer(\"Drawn Features\")\n", " if draw_layer is not None:\n", " self.remove(draw_layer)\n", " output.clear_output()\n", "\n", " reset_btn.on_click(reset_btn_click)\n", "\n", "\n", "@solara.component\n", "def Page():\n", " with solara.Column(style={\"min-width\": \"500px\"}):\n", " Map.element(\n", " center=[20, -0],\n", " zoom=2,\n", " height=\"750px\",\n", " zoom_ctrl=False,\n", " measure_ctrl=False,\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Page()" ] } ], "metadata": { "kernelspec": { "display_name": "geo", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" } }, "nbformat": 4, "nbformat_minor": 2 }