diff --git a/docs/notebooks/nlcd_app.ipynb b/docs/notebooks/nlcd_app.ipynb new file mode 100644 index 0000000000..288e4a09cc --- /dev/null +++ b/docs/notebooks/nlcd_app.ipynb @@ -0,0 +1,214 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a6624f5d-8d87-41e1-949e-e01ea4bfd1fd", + "metadata": {}, + "outputs": [], + "source": [ + "# Import libraries\n", + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b37a322-6723-4eef-b248-eca735b2fb11", + "metadata": {}, + "outputs": [], + "source": [ + "# Create an interactive map by specifying the center (lat, lon) and zoom level (1-18).\n", + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b939af3-e209-44fd-94cb-48027334ad71", + "metadata": {}, + "outputs": [], + "source": [ + "# Import the NLCD collection.\n", + "dataset = ee.ImageCollection('USGS/NLCD_RELEASES/2016_REL')\n", + "\n", + "# Filter the collection to the 2016 product.\n", + "nlcd2016 = dataset.filter(ee.Filter.eq('system:index', '2016')).first()\n", + "\n", + "# Select the land cover band.\n", + "landcover = nlcd2016.select('landcover')\n", + "\n", + "# Display land cover on the map.\n", + "Map.addLayer(landcover, {}, 'NLCD 2016')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc45b8da", + "metadata": {}, + "outputs": [], + "source": [ + "# Add the NLCD legend to the map.\n", + "Map.add_legend(legend_title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76b01ae9-d730-417f-88ff-143d0d4c20d6", + "metadata": {}, + "outputs": [], + "source": [ + "# # To add a custom legend to the map, uncomment the following code and modify the legend dictionary.\n", + "# legend_dict = {\n", + "# '11 Open Water': '466b9f',\n", + "# '12 Perennial Ice/Snow': 'd1def8',\n", + "# '21 Developed, Open Space': 'dec5c5',\n", + "# '22 Developed, Low Intensity': 'd99282',\n", + "# '23 Developed, Medium Intensity': 'eb0000',\n", + "# '24 Developed High Intensity': 'ab0000',\n", + "# '31 Barren Land (Rock/Sand/Clay)': 'b3ac9f',\n", + "# '41 Deciduous Forest': '68ab5f',\n", + "# '42 Evergreen Forest': '1c5f2c',\n", + "# '43 Mixed Forest': 'b5c58f',\n", + "# '51 Dwarf Scrub': 'af963c',\n", + "# '52 Shrub/Scrub': 'ccb879',\n", + "# '71 Grassland/Herbaceous': 'dfdfc2',\n", + "# '72 Sedge/Herbaceous': 'd1d182',\n", + "# '73 Lichens': 'a3cc51',\n", + "# '74 Moss': '82ba9e',\n", + "# '81 Pasture/Hay': 'dcd939',\n", + "# '82 Cultivated Crops': 'ab6c28',\n", + "# '90 Woody Wetlands': 'b8d9eb',\n", + "# '95 Emergent Herbaceous Wetlands': '6c9fb8'\n", + "# }\n", + "# Map.add_legend(legend_title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44c16a8e-7d13-4e46-bfaf-12178aa1b0be", + "metadata": {}, + "outputs": [], + "source": [ + "# Print the list of system ids of all available NLCD images.\n", + "dataset.aggregate_array(\"system:id\").getInfo()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a49fbecc-b0bf-4010-83b1-8628f5b05459", + "metadata": {}, + "outputs": [], + "source": [ + "# Select the seven NLCD epoches after 2000.\n", + "years = ['2001', '2004', '2006', '2008', '2011', '2013', '2016']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf361b54", + "metadata": {}, + "outputs": [], + "source": [ + "# Get an NLCD image by year.\n", + "def getNLCD(year):\n", + " # Import the NLCD collection.\n", + " dataset = ee.ImageCollection('USGS/NLCD_RELEASES/2016_REL')\n", + "\n", + " # Filter the collection by year.\n", + " nlcd = dataset.filter(ee.Filter.eq('system:index', year)).first()\n", + " \n", + " # Select the land cover band.\n", + " landcover = nlcd.select('landcover');\n", + " return landcover" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c0bbf8a-d4c9-402e-b0ff-b53f14d836bf", + "metadata": {}, + "outputs": [], + "source": [ + "## Create an NLCD image collection for the selected years.\n", + "collection = ee.ImageCollection(ee.List(years).map(lambda year: getNLCD(year)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dcd6df2", + "metadata": {}, + "outputs": [], + "source": [ + "# Print the list of system ids of selected NLCD images.\n", + "collection.aggregate_array('system:id').getInfo()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a5eac53", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a list of labels to populate the dropdown list. \n", + "labels = [f'NLCD {year}' for year in years]\n", + "labels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78e89ca5", + "metadata": {}, + "outputs": [], + "source": [ + "# Add a split-panel map for visualizing NLCD land cover change.\n", + "Map.ts_inspector(left_ts=collection, right_ts=collection, left_names=labels, right_names=labels)\n", + "Map" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.10" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/notebooks/nlcd_app.ipynb b/examples/notebooks/nlcd_app.ipynb new file mode 100644 index 0000000000..288e4a09cc --- /dev/null +++ b/examples/notebooks/nlcd_app.ipynb @@ -0,0 +1,214 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a6624f5d-8d87-41e1-949e-e01ea4bfd1fd", + "metadata": {}, + "outputs": [], + "source": [ + "# Import libraries\n", + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b37a322-6723-4eef-b248-eca735b2fb11", + "metadata": {}, + "outputs": [], + "source": [ + "# Create an interactive map by specifying the center (lat, lon) and zoom level (1-18).\n", + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b939af3-e209-44fd-94cb-48027334ad71", + "metadata": {}, + "outputs": [], + "source": [ + "# Import the NLCD collection.\n", + "dataset = ee.ImageCollection('USGS/NLCD_RELEASES/2016_REL')\n", + "\n", + "# Filter the collection to the 2016 product.\n", + "nlcd2016 = dataset.filter(ee.Filter.eq('system:index', '2016')).first()\n", + "\n", + "# Select the land cover band.\n", + "landcover = nlcd2016.select('landcover')\n", + "\n", + "# Display land cover on the map.\n", + "Map.addLayer(landcover, {}, 'NLCD 2016')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc45b8da", + "metadata": {}, + "outputs": [], + "source": [ + "# Add the NLCD legend to the map.\n", + "Map.add_legend(legend_title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76b01ae9-d730-417f-88ff-143d0d4c20d6", + "metadata": {}, + "outputs": [], + "source": [ + "# # To add a custom legend to the map, uncomment the following code and modify the legend dictionary.\n", + "# legend_dict = {\n", + "# '11 Open Water': '466b9f',\n", + "# '12 Perennial Ice/Snow': 'd1def8',\n", + "# '21 Developed, Open Space': 'dec5c5',\n", + "# '22 Developed, Low Intensity': 'd99282',\n", + "# '23 Developed, Medium Intensity': 'eb0000',\n", + "# '24 Developed High Intensity': 'ab0000',\n", + "# '31 Barren Land (Rock/Sand/Clay)': 'b3ac9f',\n", + "# '41 Deciduous Forest': '68ab5f',\n", + "# '42 Evergreen Forest': '1c5f2c',\n", + "# '43 Mixed Forest': 'b5c58f',\n", + "# '51 Dwarf Scrub': 'af963c',\n", + "# '52 Shrub/Scrub': 'ccb879',\n", + "# '71 Grassland/Herbaceous': 'dfdfc2',\n", + "# '72 Sedge/Herbaceous': 'd1d182',\n", + "# '73 Lichens': 'a3cc51',\n", + "# '74 Moss': '82ba9e',\n", + "# '81 Pasture/Hay': 'dcd939',\n", + "# '82 Cultivated Crops': 'ab6c28',\n", + "# '90 Woody Wetlands': 'b8d9eb',\n", + "# '95 Emergent Herbaceous Wetlands': '6c9fb8'\n", + "# }\n", + "# Map.add_legend(legend_title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44c16a8e-7d13-4e46-bfaf-12178aa1b0be", + "metadata": {}, + "outputs": [], + "source": [ + "# Print the list of system ids of all available NLCD images.\n", + "dataset.aggregate_array(\"system:id\").getInfo()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a49fbecc-b0bf-4010-83b1-8628f5b05459", + "metadata": {}, + "outputs": [], + "source": [ + "# Select the seven NLCD epoches after 2000.\n", + "years = ['2001', '2004', '2006', '2008', '2011', '2013', '2016']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf361b54", + "metadata": {}, + "outputs": [], + "source": [ + "# Get an NLCD image by year.\n", + "def getNLCD(year):\n", + " # Import the NLCD collection.\n", + " dataset = ee.ImageCollection('USGS/NLCD_RELEASES/2016_REL')\n", + "\n", + " # Filter the collection by year.\n", + " nlcd = dataset.filter(ee.Filter.eq('system:index', year)).first()\n", + " \n", + " # Select the land cover band.\n", + " landcover = nlcd.select('landcover');\n", + " return landcover" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c0bbf8a-d4c9-402e-b0ff-b53f14d836bf", + "metadata": {}, + "outputs": [], + "source": [ + "## Create an NLCD image collection for the selected years.\n", + "collection = ee.ImageCollection(ee.List(years).map(lambda year: getNLCD(year)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dcd6df2", + "metadata": {}, + "outputs": [], + "source": [ + "# Print the list of system ids of selected NLCD images.\n", + "collection.aggregate_array('system:id').getInfo()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a5eac53", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a list of labels to populate the dropdown list. \n", + "labels = [f'NLCD {year}' for year in years]\n", + "labels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78e89ca5", + "metadata": {}, + "outputs": [], + "source": [ + "# Add a split-panel map for visualizing NLCD land cover change.\n", + "Map.ts_inspector(left_ts=collection, right_ts=collection, left_names=labels, right_names=labels)\n", + "Map" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.10" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/geemap/geemap.py b/geemap/geemap.py index 3707dcc9c7..cc01f5a715 100644 --- a/geemap/geemap.py +++ b/geemap/geemap.py @@ -2333,6 +2333,8 @@ def ts_inspector( right_names, left_vis={}, right_vis={}, + width="130px", + **kwargs, ): """Creates a split-panel map for inspecting timeseries images. @@ -2343,7 +2345,11 @@ def ts_inspector( right_names (list): A list of names to show under the right dropdown. left_vis (dict, optional): Visualization parameters for the left layer. Defaults to {}. right_vis (dict, optional): Visualization parameters for the right layer. Defaults to {}. + width (str, optional): The width of the dropdown list. Defaults to '130px'. """ + controls = self.controls + layers = self.layers + left_count = int(left_ts.size().getInfo()) right_count = int(right_ts.size().getInfo()) @@ -2372,8 +2378,8 @@ def ts_inspector( self.clear_controls() left_dropdown = widgets.Dropdown(options=left_names, value=None) right_dropdown = widgets.Dropdown(options=right_names, value=None) - left_dropdown.layout.max_width = "130px" - right_dropdown.layout.max_width = "130px" + left_dropdown.layout.max_width = width + right_dropdown.layout.max_width = width left_control = ipyleaflet.WidgetControl( widget=left_dropdown, position="topleft" @@ -2453,6 +2459,27 @@ def right_dropdown_change(change): right_dropdown.observe(right_dropdown_change, names="value") + close_button = widgets.ToggleButton( + value=False, + tooltip="Close the tool", + icon="times", + # button_style="primary", + layout=widgets.Layout( + height="28px", width="28px", padding="0px 0px 0px 4px" + ), + ) + + def close_btn_click(change): + if change["new"]: + self.controls = controls + self.clear_layers() + self.layers = layers + + close_button.observe(close_btn_click, "value") + close_control = ipyleaflet.WidgetControl( + widget=close_button, position="bottomright" + ) + try: split_control = ipyleaflet.SplitMapControl( @@ -2460,6 +2487,8 @@ def right_dropdown_change(change): ) self.add_control(split_control) + self.add_control(close_control) + except Exception as e: raise Exception(e) diff --git a/mkdocs.yml b/mkdocs.yml index 931459feb9..52071dd325 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -176,6 +176,7 @@ nav: - notebooks/local_rf_training.ipynb - notebooks/mouse_click_coordinates.ipynb - notebooks/netcdf.ipynb + - notebooks/nlcd_app.ipynb - notebooks/notebook_template.ipynb - notebooks/oil_palm_and_rubber_plantation.ipynb - notebooks/otsu.ipynb