diff --git a/docs/notebooks/00_geemap_colab.ipynb b/docs/notebooks/00_geemap_colab.ipynb index d21c561013..9b6a1709b7 100644 --- a/docs/notebooks/00_geemap_colab.ipynb +++ b/docs/notebooks/00_geemap_colab.ipynb @@ -70,7 +70,6 @@ { "cell_type": "code", "execution_count": null, - "id": "9646abfa", "metadata": {}, "outputs": [], "source": [ diff --git a/docs/notebooks/12_zonal_statistics.ipynb b/docs/notebooks/12_zonal_statistics.ipynb index 4daa8c9f33..b25bb1f550 100644 --- a/docs/notebooks/12_zonal_statistics.ipynb +++ b/docs/notebooks/12_zonal_statistics.ipynb @@ -91,7 +91,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -101,8 +101,8 @@ "outputs": [], "source": [ "out_landsat_stats = os.path.join(out_dir, 'landsat_stats.csv')\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -134,4 +134,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/notebooks/131_arcgis.ipynb b/docs/notebooks/131_arcgis.ipynb index 0278f3f1b8..8d730d6197 100644 --- a/docs/notebooks/131_arcgis.ipynb +++ b/docs/notebooks/131_arcgis.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -20,7 +19,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -59,7 +57,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -84,7 +81,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/docs/notebooks/137_create_grid.ipynb b/docs/notebooks/137_create_grid.ipynb index 31e1bd8e27..8294632397 100644 --- a/docs/notebooks/137_create_grid.ipynb +++ b/docs/notebooks/137_create_grid.ipynb @@ -1,175 +1,175 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"Open\n", - "\n", - "**Creating a rectangular grid covering a region of interest for computing zonal statistics**\n", - "\n", - "Uncomment the following line to install [geemap](https://geemap.org) if needed." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install git+https://github.com/gee-community/geemap.git" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Import libraries" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Update the package and restart the kernel if you run into errors." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# geemap.update_package()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add temperature data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.ImageCollection('NOAA/GFS0P25').first().select('temperature_2m_above_ground')\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "Map.addLayer(image, vis_params, 'Temperature')\n", - "Map.add_colorbar(vis_params, label=\"Temperature (°C)\")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a grid covering the area of interest." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geometry = ee.Geometry.BBox(-130, 24, -68, 50)\n", - "grid = geemap.create_grid(geometry, 2e5)\n", - "Map.addLayer(grid, {}, 'Grid')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics based on the image and grid. In this case, we are computing the mean temperature for each grid cell." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.zonal_stats(\n", - " image, grid, statistics_type='MEAN', scale=2e5, return_fc=True\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add the mean temperature grid to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.add_styled_vector(\n", - " stats, column=\"mean\", palette='coolwarm', layer_name=\"Mean Temperature\"\n", - ")\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](https://i.imgur.com/Kwe5eom.png)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"Open\n", + "\n", + "**Creating a rectangular grid covering a region of interest for computing zonal statistics**\n", + "\n", + "Uncomment the following line to install [geemap](https://geemap.org) if needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install git+https://github.com/gee-community/geemap.git" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Update the package and restart the kernel if you run into errors." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# geemap.update_package()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add temperature data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.ImageCollection('NOAA/GFS0P25').first().select('temperature_2m_above_ground')\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "Map.addLayer(image, vis_params, 'Temperature')\n", + "Map.add_colorbar(vis_params, label=\"Temperature (°C)\")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a grid covering the area of interest." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geometry = ee.Geometry.BBox(-130, 24, -68, 50)\n", + "grid = geemap.create_grid(geometry, 2e5)\n", + "Map.addLayer(grid, {}, 'Grid')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics based on the image and grid. In this case, we are computing the mean temperature for each grid cell." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.zonal_stats(\n", + " image, grid, stat_type='MEAN', scale=2e5, return_fc=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add the mean temperature grid to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.add_styled_vector(\n", + " stats, column=\"mean\", palette='coolwarm', layer_name=\"Mean Temperature\"\n", + ")\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](https://i.imgur.com/Kwe5eom.png)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/docs/notebooks/13_zonal_statistics_by_group.ipynb b/docs/notebooks/13_zonal_statistics_by_group.ipynb index 306d072023..111fcef373 100644 --- a/docs/notebooks/13_zonal_statistics_by_group.ipynb +++ b/docs/notebooks/13_zonal_statistics_by_group.ipynb @@ -97,11 +97,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilometers\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -211,11 +211,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " countries,\n", " global_stats,\n", - " statistics_type='PERCENTAGE',\n", + " stat_type='PERCENTAGE',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -240,4 +240,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/notebooks/58_add_vector.ipynb b/docs/notebooks/58_add_vector.ipynb index 03f91a37b5..13828a538b 100644 --- a/docs/notebooks/58_add_vector.ipynb +++ b/docs/notebooks/58_add_vector.ipynb @@ -126,7 +126,6 @@ { "cell_type": "code", "execution_count": null, - "id": "e1ddca8c", "metadata": {}, "outputs": [], "source": [ @@ -136,7 +135,6 @@ }, { "cell_type": "markdown", - "id": "e441583e", "metadata": {}, "source": [ "Uncomment to install `PyCRS` as needed" @@ -145,7 +143,6 @@ { "cell_type": "code", "execution_count": null, - "id": "d0b3cf80", "metadata": {}, "outputs": [], "source": [ diff --git a/docs/usage.md b/docs/usage.md index ffee7ef3d7..ab5e6941c1 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -116,13 +116,13 @@ geemap.ee_to_numpy(ee_object, bands, region, properties, default_value) To calculate zonal statistics: ```python -geemap.zonal_statistics(in_value_raster, in_zone_vector, out_file_path, statistics_type='MEAN') +geemap.zonal_stats(in_value_raster, in_zone_vector, out_file_path, stat_type='MEAN') ``` To calculate zonal statistics by group: ```python -geemap.zonal_statistics_by_group(in_value_raster, in_zone_vector, out_file_path, statistics_type='SUM') +geemap.zonal_stats_by_group(in_value_raster, in_zone_vector, out_file_path, stat_type='SUM') ``` To create a split-panel Map: diff --git a/docs/workshops/AGU_2023.ipynb b/docs/workshops/AGU_2023.ipynb index 3f27fb97c1..1a86f4fd98 100644 --- a/docs/workshops/AGU_2023.ipynb +++ b/docs/workshops/AGU_2023.ipynb @@ -1,3219 +1,3219 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", - "\n", - "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", - "\n", - "- Notebook: \n", - "- Earth Engine: \n", - "- Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the workshop presented at the [AGU Annual Meeting 2023](https://www.agu.org/fall-meeting).\n", - "\n", - "### Abstract\n", - "\n", - "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", - "\n", - "### Prerequisites\n", - "\n", - "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", - "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", - "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", - "\n", - "### Change Colab dark theme\n", - "\n", - "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", - "\n", - "![](https://i.imgur.com/EJ0GDP8.png)\n", - "\n", - "\n", - "### Install geemap\n", - "\n", - "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install -U \"geemap[workshop]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", - "\n", - "```bash\n", - "conda create -n gee python=3.11\n", - "conda activate gee\n", - "conda install -c conda-forge mamba\n", - "mamba install -c conda-forge geemap pygis\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries\n", - "\n", - "Import the earthengine-api and geemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(basemap='Esri.WorldImagery')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('Esri.WorldTopoMap')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also change basemaps interactively using the basemap GUI." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", - "}\n", - "m.add_layer(image, vis_params, 'SRTM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "m.set_center(-73.9596, 40.7688, 12)\n", - "m.add_layer(fc, {}, 'Census roads')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "m.add_layer(fc, {}, 'Louisiana')\n", - "m.center_object(fc, 7)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "m.add_layer(fc, {}, 'West Coast')\n", - "m.center_object(fc, 5)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = m.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "m.add_layer(fc, {}, 'Southeastern U.S.')\n", - "m.center_object(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "m.add_layer(states.style(**style), {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "m.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "m.add_layer(dataset, {}, 'GAP CONUS')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import get_metadata\n", - "\n", - "get_metadata(DATA.USGS_GAP_CONUS_2011)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Converting Earth Engine JavaScripts to Python\n", - "\n", - "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load an image.\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", - "\n", - "# Define the visualization parameters.\n", - "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "# Center the map and display the image.\n", - "m.set_center(-122.1899, 37.5010, 10)\n", - "# San Francisco Bay\n", - "m.add_layer(image, vizParams, 'False color composite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/i3IT0lF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 1 (10 mins)\n", - "\n", - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_layer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m.add('inspector')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", - "m.add_plot_gui()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Landsat." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Hyperion." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", - "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(add_google_map=False)\n", - "\n", - "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make the color bar background transparent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\",\n", - " transparent_bg=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel map and linked maps\n", - "\n", - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", - "\n", - "m.split_map(left_layer, right_layer)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Linked maps\n", - "\n", - "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = (\n", - " ee.ImageCollection('COPERNICUS/S2')\n", - " .filterDate('2018-09-01', '2018-09-30')\n", - " .map(lambda img: img.divide(10000))\n", - " .median()\n", - ")\n", - "\n", - "vis_params = [\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - "]\n", - "\n", - "labels = [\n", - " 'Natural Color (B4/B3/B2)',\n", - " 'Land/Water (B8/B11/B4)',\n", - " 'Color Infrared (B8/B4/B3)',\n", - " 'Vegetation (B12/B11/B4)',\n", - "]\n", - "\n", - "geemap.linked_maps(\n", - " rows=2,\n", - " cols=2,\n", - " height=\"300px\",\n", - " center=[38.4151, 21.2712],\n", - " zoom=12,\n", - " ee_objects=[image],\n", - " vis_params=vis_params,\n", - " labels=labels,\n", - " label_position=\"topright\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Timeseries inspector and time slider\n", - "\n", - "#### Timeseries inspector\n", - "\n", - "Check the available years of NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", - "vis_params = {'bands': ['landcover']}\n", - "years = collection.aggregate_array('system:index').getInfo()\n", - "years" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.ts_inspector(\n", - " left_ts=collection,\n", - " right_ts=collection,\n", - " left_names=years,\n", - " right_names=years,\n", - " left_vis=vis_params,\n", - " right_vis=vis_params,\n", - " width='80px',\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Time slider\n", - "\n", - "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", - "\n", - "Create a map for visualizing MODIS vegetation data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", - " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", - " .select(\"NDVI\")\n", - ")\n", - "vis_params = {\n", - " 'min': 0.0,\n", - " 'max': 1.0,\n", - " 'palette': 'ndvi',\n", - "}\n", - "\n", - "m.add_time_slider(collection, vis_params, time_interval=2)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a map for visualizing weather data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('NOAA/GFS0P25')\n", - " .filterDate('2018-12-22', '2018-12-23')\n", - " .limit(24)\n", - " .select('temperature_2m_above_ground')\n", - ")\n", - "\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "\n", - "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", - "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualizing Sentinel-2 imagery" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", - "\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", - " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", - ")\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "\n", - "m.add_time_slider(collection, vis_params)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "![](https://i.imgur.com/1b62CeI.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "m.center_object(centroid, 8)\n", - "m.add_layer(image, vis, \"Landsat-8\")\n", - "m.add_layer(centroid, {}, 'Centroid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = dataset.select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics with two images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dem = ee.Image('USGS/3DEP/10m')\n", - "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", - "m.add_layer(dem, vis, 'DEM')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Computer the mean elevation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", - "stats" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats.to_csv('mean.csv', index=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute the standard deviation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df('std.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Coordinate grids and fishnets\n", - "\n", - "#### Creating coordinate grids\n", - "\n", - "Create a latitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(lat_grid)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a longitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a rectangular grid with a 10-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grid = geemap.latlon_grid(\n", - " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating fishnets\n", - "\n", - "Create a fishnet based on an Earth Engine geometry." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with a 2-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a new map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Draw a polygon on the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.Polygon(\n", - " [\n", - " [\n", - " [-64.602356, -1.127399],\n", - " [-68.821106, -12.625598],\n", - " [-60.647278, -22.498601],\n", - " [-47.815247, -21.111406],\n", - " [-43.860168, -8.913564],\n", - " [-54.582825, -0.775886],\n", - " [-60.823059, 0.454555],\n", - " [-64.602356, -1.127399],\n", - " ]\n", - " ]\n", - " )\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Land use and land cover change analysis\n", - "\n", - "#### Forest cover mapping\n", - "\n", - "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", - "dataset.bandNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", - "first_image = dataset.select(first_bands)\n", - "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2022." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", - "last_image = dataset.select(last_bands)\n", - "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the tree cover imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "treecover = dataset.select(['treecover2000'])\n", - "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", - "name = 'Tree cover (%)'\n", - "m.add_layer(treecover, treeCoverVisParam, name)\n", - "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extract tree cover 2000 by using the threshold of 10%." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 10\n", - "treecover_bin = treecover.gte(threshold).selfMask()\n", - "treeVisParam = {'palette': ['green']}\n", - "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Forest loss and gain mapping\n", - "\n", - "Visualize forest loss." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss_year = dataset.select(['lossyear'])\n", - "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", - "layer_name = 'Tree loss year'\n", - "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", - "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare forest loss and gain." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss = dataset.select(['loss']).selfMask()\n", - "treegain = dataset.select(['gain']).selfMask()\n", - "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", - "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by country\n", - "\n", - "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", - "\n", - "Add a country boundary layer to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", - "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", - "m.add_layer(countries.style(**style), {}, 'Countries')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treecover_bin,\n", - " countries,\n", - " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pie chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart(\n", - " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'forest_cover.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treeloss.gt(0),\n", - " countries,\n", - " 'treeloss.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'treeloss.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest loss area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Analyzing forest cover gain and loss\n", - "\n", - "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", - "\n", - "![](https://i.imgur.com/NQ4UUnj.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 2 (10 mins)\n", - "\n", - "## Exporting Earth Engine data (30 mins)\n", - "\n", - "### Exporting images\n", - "\n", - "Add a Landsat image to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", - " ['B5', 'B4', 'B3']\n", - ")\n", - "\n", - "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "m.center_object(image)\n", - "m.add_layer(image, vis_params, 'Landsat')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a rectangle to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", - "fc = ee.FeatureCollection(region)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "m.add_layer(fc.style(**style), {}, 'ROI')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image projection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "projection = image.select(0).projection().getInfo()\n", - "projection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "crs = projection['crs']\n", - "crs_transform = projection['transform']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify region, crs, and crs_transform." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(\n", - " image,\n", - " filename=\"landsat_crs.tif\",\n", - " crs=crs,\n", - " crs_transform=crs_transform,\n", - " region=region,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_to_drive(\n", - " image, description='landsat', folder='export', region=region, scale=30\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "point = ee.Geometry.Point(-99.2222, 46.7816)\n", - "collection = (\n", - " ee.ImageCollection('USDA/NAIP/DOQQ')\n", - " .filterBounds(point)\n", - " .filterDate('2008-01-01', '2018-01-01')\n", - " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection.aggregate_array('system:index')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", - " ee.Filter.eq('country_na', 'Germany')\n", - ")\n", - "m.add_layer(fc, {}, \"Germany\")\n", - "m.center_object(fc)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector(fc, filename='Germany2.shp')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_geojson(fc, filename='Germany.geojson')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_csv(fc, filename='Germany.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gdf = geemap.ee_to_gdf(fc)\n", - "gdf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(fc)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector_to_drive(\n", - " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5 - Exporting images by a fishnet\n", - "\n", - "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", - "\n", - "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", - "\n", - "![](https://i.imgur.com/L1IH3fq.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", - "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", - "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", - "m.add_layer(region, {}, 'ROI')\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", - "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " m.add_layer(roi, {}, 'ROI')\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", - "\n", - "![](https://i.imgur.com/ohrXeFC.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_gui(\"timelapse\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 3 (10 mins)\n", - "\n", - "## Building interactive web apps (30 mins)\n", - "\n", - "This section is optional. We might not have enough time to cover this section.\n", - "\n", - "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", - "\n", - "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", - "\n", - "After following the instructions above, you should have a web app that looks like this:\n", - "\n", - "![](https://i.imgur.com/X3ZFyRr.png)\n", - "\n", - "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", + "\n", + "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", + "\n", + "- Notebook: \n", + "- Earth Engine: \n", + "- Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the workshop presented at the [AGU Annual Meeting 2023](https://www.agu.org/fall-meeting).\n", + "\n", + "### Abstract\n", + "\n", + "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", + "\n", + "### Prerequisites\n", + "\n", + "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", + "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", + "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", + "\n", + "### Change Colab dark theme\n", + "\n", + "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", + "\n", + "![](https://i.imgur.com/EJ0GDP8.png)\n", + "\n", + "\n", + "### Install geemap\n", + "\n", + "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install -U \"geemap[workshop]\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", + "\n", + "```bash\n", + "conda create -n gee python=3.11\n", + "conda activate gee\n", + "conda install -c conda-forge mamba\n", + "mamba install -c conda-forge geemap pygis\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries\n", + "\n", + "Import the earthengine-api and geemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(basemap='Esri.WorldImagery')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('Esri.WorldTopoMap')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also change basemaps interactively using the basemap GUI." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", + "}\n", + "m.add_layer(image, vis_params, 'SRTM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "m.set_center(-73.9596, 40.7688, 12)\n", + "m.add_layer(fc, {}, 'Census roads')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "m.add_layer(fc, {}, 'Louisiana')\n", + "m.center_object(fc, 7)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "m.add_layer(fc, {}, 'West Coast')\n", + "m.center_object(fc, 5)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = m.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "m.add_layer(fc, {}, 'Southeastern U.S.')\n", + "m.center_object(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "m.add_layer(states.style(**style), {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "m.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "m.add_layer(dataset, {}, 'GAP CONUS')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import get_metadata\n", + "\n", + "get_metadata(DATA.USGS_GAP_CONUS_2011)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Converting Earth Engine JavaScripts to Python\n", + "\n", + "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load an image.\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", + "\n", + "# Define the visualization parameters.\n", + "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "# Center the map and display the image.\n", + "m.set_center(-122.1899, 37.5010, 10)\n", + "# San Francisco Bay\n", + "m.add_layer(image, vizParams, 'False color composite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/i3IT0lF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 1 (10 mins)\n", + "\n", + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_layer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m.add('inspector')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", + "m.add_plot_gui()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Landsat." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Hyperion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", + "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(add_google_map=False)\n", + "\n", + "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the color bar background transparent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\",\n", + " transparent_bg=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel map and linked maps\n", + "\n", + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", + "\n", + "m.split_map(left_layer, right_layer)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linked maps\n", + "\n", + "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = (\n", + " ee.ImageCollection('COPERNICUS/S2')\n", + " .filterDate('2018-09-01', '2018-09-30')\n", + " .map(lambda img: img.divide(10000))\n", + " .median()\n", + ")\n", + "\n", + "vis_params = [\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + "]\n", + "\n", + "labels = [\n", + " 'Natural Color (B4/B3/B2)',\n", + " 'Land/Water (B8/B11/B4)',\n", + " 'Color Infrared (B8/B4/B3)',\n", + " 'Vegetation (B12/B11/B4)',\n", + "]\n", + "\n", + "geemap.linked_maps(\n", + " rows=2,\n", + " cols=2,\n", + " height=\"300px\",\n", + " center=[38.4151, 21.2712],\n", + " zoom=12,\n", + " ee_objects=[image],\n", + " vis_params=vis_params,\n", + " labels=labels,\n", + " label_position=\"topright\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Timeseries inspector and time slider\n", + "\n", + "#### Timeseries inspector\n", + "\n", + "Check the available years of NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", + "vis_params = {'bands': ['landcover']}\n", + "years = collection.aggregate_array('system:index').getInfo()\n", + "years" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.ts_inspector(\n", + " left_ts=collection,\n", + " right_ts=collection,\n", + " left_names=years,\n", + " right_names=years,\n", + " left_vis=vis_params,\n", + " right_vis=vis_params,\n", + " width='80px',\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Time slider\n", + "\n", + "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", + "\n", + "Create a map for visualizing MODIS vegetation data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", + " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", + " .select(\"NDVI\")\n", + ")\n", + "vis_params = {\n", + " 'min': 0.0,\n", + " 'max': 1.0,\n", + " 'palette': 'ndvi',\n", + "}\n", + "\n", + "m.add_time_slider(collection, vis_params, time_interval=2)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a map for visualizing weather data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('NOAA/GFS0P25')\n", + " .filterDate('2018-12-22', '2018-12-23')\n", + " .limit(24)\n", + " .select('temperature_2m_above_ground')\n", + ")\n", + "\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "\n", + "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", + "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizing Sentinel-2 imagery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", + "\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", + " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", + ")\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "\n", + "m.add_time_slider(collection, vis_params)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "![](https://i.imgur.com/1b62CeI.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "m.center_object(centroid, 8)\n", + "m.add_layer(image, vis, \"Landsat-8\")\n", + "m.add_layer(centroid, {}, 'Centroid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = dataset.select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics with two images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dem = ee.Image('USGS/3DEP/10m')\n", + "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", + "m.add_layer(dem, vis, 'DEM')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computer the mean elevation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", + "stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats.to_csv('mean.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the standard deviation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df('std.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coordinate grids and fishnets\n", + "\n", + "#### Creating coordinate grids\n", + "\n", + "Create a latitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(lat_grid)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a longitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a rectangular grid with a 10-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = geemap.latlon_grid(\n", + " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating fishnets\n", + "\n", + "Create a fishnet based on an Earth Engine geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with a 2-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a new map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Draw a polygon on the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.Polygon(\n", + " [\n", + " [\n", + " [-64.602356, -1.127399],\n", + " [-68.821106, -12.625598],\n", + " [-60.647278, -22.498601],\n", + " [-47.815247, -21.111406],\n", + " [-43.860168, -8.913564],\n", + " [-54.582825, -0.775886],\n", + " [-60.823059, 0.454555],\n", + " [-64.602356, -1.127399],\n", + " ]\n", + " ]\n", + " )\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Land use and land cover change analysis\n", + "\n", + "#### Forest cover mapping\n", + "\n", + "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", + "dataset.bandNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", + "first_image = dataset.select(first_bands)\n", + "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", + "last_image = dataset.select(last_bands)\n", + "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the tree cover imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "treecover = dataset.select(['treecover2000'])\n", + "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", + "name = 'Tree cover (%)'\n", + "m.add_layer(treecover, treeCoverVisParam, name)\n", + "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract tree cover 2000 by using the threshold of 10%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "threshold = 10\n", + "treecover_bin = treecover.gte(threshold).selfMask()\n", + "treeVisParam = {'palette': ['green']}\n", + "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Forest loss and gain mapping\n", + "\n", + "Visualize forest loss." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss_year = dataset.select(['lossyear'])\n", + "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", + "layer_name = 'Tree loss year'\n", + "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", + "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare forest loss and gain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss = dataset.select(['loss']).selfMask()\n", + "treegain = dataset.select(['gain']).selfMask()\n", + "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", + "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by country\n", + "\n", + "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", + "\n", + "Add a country boundary layer to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", + "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", + "m.add_layer(countries.style(**style), {}, 'Countries')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treecover_bin,\n", + " countries,\n", + " 'forest_cover.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a pie chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart(\n", + " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'forest_cover.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treeloss.gt(0),\n", + " countries,\n", + " 'treeloss.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'treeloss.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest loss area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Analyzing forest cover gain and loss\n", + "\n", + "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", + "\n", + "![](https://i.imgur.com/NQ4UUnj.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 2 (10 mins)\n", + "\n", + "## Exporting Earth Engine data (30 mins)\n", + "\n", + "### Exporting images\n", + "\n", + "Add a Landsat image to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", + " ['B5', 'B4', 'B3']\n", + ")\n", + "\n", + "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "m.center_object(image)\n", + "m.add_layer(image, vis_params, 'Landsat')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a rectangle to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", + "fc = ee.FeatureCollection(region)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "m.add_layer(fc.style(**style), {}, 'ROI')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image projection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "projection = image.select(0).projection().getInfo()\n", + "projection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "crs = projection['crs']\n", + "crs_transform = projection['transform']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify region, crs, and crs_transform." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(\n", + " image,\n", + " filename=\"landsat_crs.tif\",\n", + " crs=crs,\n", + " crs_transform=crs_transform,\n", + " region=region,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_to_drive(\n", + " image, description='landsat', folder='export', region=region, scale=30\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "point = ee.Geometry.Point(-99.2222, 46.7816)\n", + "collection = (\n", + " ee.ImageCollection('USDA/NAIP/DOQQ')\n", + " .filterBounds(point)\n", + " .filterDate('2008-01-01', '2018-01-01')\n", + " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection.aggregate_array('system:index')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", + " ee.Filter.eq('country_na', 'Germany')\n", + ")\n", + "m.add_layer(fc, {}, \"Germany\")\n", + "m.center_object(fc)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector(fc, filename='Germany2.shp')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_geojson(fc, filename='Germany.geojson')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_csv(fc, filename='Germany.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdf = geemap.ee_to_gdf(fc)\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(fc)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector_to_drive(\n", + " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 5 - Exporting images by a fishnet\n", + "\n", + "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", + "\n", + "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", + "\n", + "![](https://i.imgur.com/L1IH3fq.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", + "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", + "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", + "m.add_layer(region, {}, 'ROI')\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", + "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " m.add_layer(roi, {}, 'ROI')\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", + "\n", + "![](https://i.imgur.com/ohrXeFC.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_gui(\"timelapse\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 3 (10 mins)\n", + "\n", + "## Building interactive web apps (30 mins)\n", + "\n", + "This section is optional. We might not have enough time to cover this section.\n", + "\n", + "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", + "\n", + "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", + "\n", + "After following the instructions above, you should have a web app that looks like this:\n", + "\n", + "![](https://i.imgur.com/X3ZFyRr.png)\n", + "\n", + "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/docs/workshops/AmericaView_2023.ipynb b/docs/workshops/AmericaView_2023.ipynb index 448e5f033d..7a9689557c 100644 --- a/docs/workshops/AmericaView_2023.ipynb +++ b/docs/workshops/AmericaView_2023.ipynb @@ -1167,7 +1167,7 @@ "source": [ "out_dem_stats = 'dem_stats.csv'\n", "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", ")" ] }, @@ -1182,7 +1182,7 @@ " landsat,\n", " states,\n", " out_landsat_stats,\n", - " statistics_type='MEAN',\n", + " stat_type='MEAN',\n", " scale=1000,\n", " return_fc=False,\n", ")" @@ -1230,7 +1230,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -1248,7 +1248,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", + " stat_type='PERCENTAGE',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -1997,4 +1997,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/Crop_Mapping_2022.ipynb b/docs/workshops/Crop_Mapping_2022.ipynb index ecc0d157f7..222d6dc7c2 100644 --- a/docs/workshops/Crop_Mapping_2022.ipynb +++ b/docs/workshops/Crop_Mapping_2022.ipynb @@ -256,7 +256,7 @@ "outputs": [], "source": [ "geemap.zonal_stats(\n", - " cropland, africa, 'esa_cropland.csv', statistics_type='SUM', scale=1000\n", + " cropland, africa, 'esa_cropland.csv', stat_type='SUM', scale=1000\n", ")" ] }, @@ -447,7 +447,7 @@ "outputs": [], "source": [ "geemap.zonal_stats(\n", - " cropland_ts, africa, 'esri_cropland.csv', statistics_type='SUM', scale=1000\n", + " cropland_ts, africa, 'esri_cropland.csv', stat_type='SUM', scale=1000\n", ")" ] }, @@ -519,7 +519,7 @@ " cropland_gain,\n", " countries,\n", " 'esri_cropland_gain.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " scale=1000,\n", ")" ] @@ -572,7 +572,7 @@ " cropland_loss,\n", " countries,\n", " 'esri_cropland_loss.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " scale=1000,\n", ")" ] @@ -733,4 +733,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/G4G_2023.ipynb b/docs/workshops/G4G_2023.ipynb index bdec022c67..c8080b8cd1 100644 --- a/docs/workshops/G4G_2023.ipynb +++ b/docs/workshops/G4G_2023.ipynb @@ -1,3235 +1,3235 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", - "\n", - "**Introduction to Google Earth Engine in Python**\n", - "\n", - "- Notebook: \n", - "- Earth Engine: \n", - "- Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the workshop presented at the [Geo for Good Summit 2023](https://earthoutreachonair.withgoogle.com/events/geoforgood23). Check out [this link](https://earthoutreachonair.withgoogle.com/events/geoforgood23?tab=g4gagenda&expand=module:agenda) for more information about the workshop.\n", - "\n", - "### Abstract\n", - "\n", - "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", - "\n", - "### Prerequisites\n", - "\n", - "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", - "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", - "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", - "\n", - "### Change Colab dark theme\n", - "\n", - "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", - "\n", - "![](https://i.imgur.com/EJ0GDP8.png)\n", - "\n", - "\n", - "### Install geemap\n", - "\n", - "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install -U \"geemap[workshop]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", - "\n", - "```bash\n", - "conda create -n gee python=3.11\n", - "conda activate gee\n", - "conda install -c conda-forge mamba\n", - "mamba install -c conda-forge geemap pygis\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries\n", - "\n", - "Import the earthengine-api and geemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ee.Authenticate()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ee.Initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(basemap='Esri.WorldImagery')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('Esri.WorldTopoMap')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also change basemaps interactively using the basemap GUI." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", - "}\n", - "m.add_layer(image, vis_params, 'SRTM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "m.set_center(-73.9596, 40.7688, 12)\n", - "m.add_layer(fc, {}, 'Census roads')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "m.add_layer(fc, {}, 'Louisiana')\n", - "m.center_object(fc, 7)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "m.add_layer(fc, {}, 'West Coast')\n", - "m.center_object(fc, 5)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = m.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "m.add_layer(fc, {}, 'Southeastern U.S.')\n", - "m.center_object(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "m.add_layer(states.style(**style), {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "m.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "m.add_layer(dataset, {}, 'GAP CONUS')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import get_metadata\n", - "\n", - "get_metadata(DATA.USGS_GAP_CONUS_2011)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Converting Earth Engine JavaScripts to Python\n", - "\n", - "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load an image.\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", - "\n", - "# Define the visualization parameters.\n", - "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "# Center the map and display the image.\n", - "m.set_center(-122.1899, 37.5010, 10)\n", - "# San Francisco Bay\n", - "m.add_layer(image, vizParams, 'False color composite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/i3IT0lF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 1 (10 mins)\n", - "\n", - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_layer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m.add('inspector')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", - "m.add_plot_gui()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Landsat." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Hyperion." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", - "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(add_google_map=False)\n", - "\n", - "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make the color bar background transparent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\",\n", - " transparent_bg=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel map and linked maps\n", - "\n", - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", - "\n", - "m.split_map(left_layer, right_layer)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Linked maps\n", - "\n", - "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = (\n", - " ee.ImageCollection('COPERNICUS/S2')\n", - " .filterDate('2018-09-01', '2018-09-30')\n", - " .map(lambda img: img.divide(10000))\n", - " .median()\n", - ")\n", - "\n", - "vis_params = [\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - "]\n", - "\n", - "labels = [\n", - " 'Natural Color (B4/B3/B2)',\n", - " 'Land/Water (B8/B11/B4)',\n", - " 'Color Infrared (B8/B4/B3)',\n", - " 'Vegetation (B12/B11/B4)',\n", - "]\n", - "\n", - "geemap.linked_maps(\n", - " rows=2,\n", - " cols=2,\n", - " height=\"300px\",\n", - " center=[38.4151, 21.2712],\n", - " zoom=12,\n", - " ee_objects=[image],\n", - " vis_params=vis_params,\n", - " labels=labels,\n", - " label_position=\"topright\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Timeseries inspector and time slider\n", - "\n", - "#### Timeseries inspector\n", - "\n", - "Check the available years of NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", - "vis_params = {'bands': ['landcover']}\n", - "years = collection.aggregate_array('system:index').getInfo()\n", - "years" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.ts_inspector(\n", - " left_ts=collection,\n", - " right_ts=collection,\n", - " left_names=years,\n", - " right_names=years,\n", - " left_vis=vis_params,\n", - " right_vis=vis_params,\n", - " width='80px',\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Time slider\n", - "\n", - "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", - "\n", - "Create a map for visualizing MODIS vegetation data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", - " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", - " .select(\"NDVI\")\n", - ")\n", - "vis_params = {\n", - " 'min': 0.0,\n", - " 'max': 1.0,\n", - " 'palette': 'ndvi',\n", - "}\n", - "\n", - "m.add_time_slider(collection, vis_params, time_interval=2)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a map for visualizing weather data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('NOAA/GFS0P25')\n", - " .filterDate('2018-12-22', '2018-12-23')\n", - " .limit(24)\n", - " .select('temperature_2m_above_ground')\n", - ")\n", - "\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "\n", - "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", - "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualizing Sentinel-2 imagery" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", - "\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", - " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", - ")\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "\n", - "m.add_time_slider(collection, vis_params)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "![](https://i.imgur.com/1b62CeI.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "m.center_object(centroid, 8)\n", - "m.add_layer(image, vis, \"Landsat-8\")\n", - "m.add_layer(centroid, {}, 'Centroid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = dataset.select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics with two images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dem = ee.Image('USGS/3DEP/10m')\n", - "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", - "m.add_layer(dem, vis, 'DEM')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Computer the mean elevation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", - "stats" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats.to_csv('mean.csv', index=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute the standard deviation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df('std.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Coordinate grids and fishnets\n", - "\n", - "#### Creating coordinate grids\n", - "\n", - "Create a latitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(lat_grid)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a longitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a rectangular grid with a 10-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grid = geemap.latlon_grid(\n", - " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating fishnets\n", - "\n", - "Create a fishnet based on an Earth Engine geometry." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with a 2-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a new map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Draw a polygon on the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.Polygon(\n", - " [\n", - " [\n", - " [-64.602356, -1.127399],\n", - " [-68.821106, -12.625598],\n", - " [-60.647278, -22.498601],\n", - " [-47.815247, -21.111406],\n", - " [-43.860168, -8.913564],\n", - " [-54.582825, -0.775886],\n", - " [-60.823059, 0.454555],\n", - " [-64.602356, -1.127399],\n", - " ]\n", - " ]\n", - " )\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Land use and land cover change analysis\n", - "\n", - "#### Forest cover mapping\n", - "\n", - "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", - "dataset.bandNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", - "first_image = dataset.select(first_bands)\n", - "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2022." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", - "last_image = dataset.select(last_bands)\n", - "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the tree cover imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "treecover = dataset.select(['treecover2000'])\n", - "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", - "name = 'Tree cover (%)'\n", - "m.add_layer(treecover, treeCoverVisParam, name)\n", - "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extract tree cover 2000 by using the threshold of 10%." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 10\n", - "treecover_bin = treecover.gte(threshold).selfMask()\n", - "treeVisParam = {'palette': ['green']}\n", - "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Forest loss and gain mapping\n", - "\n", - "Visualize forest loss." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss_year = dataset.select(['lossyear'])\n", - "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", - "layer_name = 'Tree loss year'\n", - "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", - "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare forest loss and gain." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss = dataset.select(['loss']).selfMask()\n", - "treegain = dataset.select(['gain']).selfMask()\n", - "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", - "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by country\n", - "\n", - "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", - "\n", - "Add a country boundary layer to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", - "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", - "m.add_layer(countries.style(**style), {}, 'Countries')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treecover_bin,\n", - " countries,\n", - " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pie chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart(\n", - " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'forest_cover.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treeloss.gt(0),\n", - " countries,\n", - " 'treeloss.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'treeloss.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest loss area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Analyzing forest cover gain and loss\n", - "\n", - "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", - "\n", - "![](https://i.imgur.com/NQ4UUnj.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 2 (10 mins)\n", - "\n", - "## Exporting Earth Engine data (30 mins)\n", - "\n", - "### Exporting images\n", - "\n", - "Add a Landsat image to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", - " ['B5', 'B4', 'B3']\n", - ")\n", - "\n", - "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "m.center_object(image)\n", - "m.add_layer(image, vis_params, 'Landsat')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a rectangle to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", - "fc = ee.FeatureCollection(region)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "m.add_layer(fc.style(**style), {}, 'ROI')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image projection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "projection = image.select(0).projection().getInfo()\n", - "projection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "crs = projection['crs']\n", - "crs_transform = projection['transform']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify region, crs, and crs_transform." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(\n", - " image,\n", - " filename=\"landsat_crs.tif\",\n", - " crs=crs,\n", - " crs_transform=crs_transform,\n", - " region=region,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_to_drive(\n", - " image, description='landsat', folder='export', region=region, scale=30\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "point = ee.Geometry.Point(-99.2222, 46.7816)\n", - "collection = (\n", - " ee.ImageCollection('USDA/NAIP/DOQQ')\n", - " .filterBounds(point)\n", - " .filterDate('2008-01-01', '2018-01-01')\n", - " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection.aggregate_array('system:index')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", - " ee.Filter.eq('country_na', 'Germany')\n", - ")\n", - "m.add_layer(fc, {}, \"Germany\")\n", - "m.center_object(fc)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector(fc, filename='Germany2.shp')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_geojson(fc, filename='Germany.geojson')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_csv(fc, filename='Germany.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gdf = geemap.ee_to_gdf(fc)\n", - "gdf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(fc)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector_to_drive(\n", - " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5 - Exporting images by a fishnet\n", - "\n", - "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", - "\n", - "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", - "\n", - "![](https://i.imgur.com/L1IH3fq.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", - "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", - "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", - "m.add_layer(region, {}, 'ROI')\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", - "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " m.add_layer(roi, {}, 'ROI')\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", - "\n", - "![](https://i.imgur.com/ohrXeFC.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_gui(\"timelapse\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 3 (10 mins)\n", - "\n", - "## Building interactive web apps (30 mins)\n", - "\n", - "This section is optional. We might not have enough time to cover this section.\n", - "\n", - "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", - "\n", - "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", - "\n", - "After following the instructions above, you should have a web app that looks like this:\n", - "\n", - "![](https://i.imgur.com/X3ZFyRr.png)\n", - "\n", - "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", + "\n", + "**Introduction to Google Earth Engine in Python**\n", + "\n", + "- Notebook: \n", + "- Earth Engine: \n", + "- Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the workshop presented at the [Geo for Good Summit 2023](https://earthoutreachonair.withgoogle.com/events/geoforgood23). Check out [this link](https://earthoutreachonair.withgoogle.com/events/geoforgood23?tab=g4gagenda&expand=module:agenda) for more information about the workshop.\n", + "\n", + "### Abstract\n", + "\n", + "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", + "\n", + "### Prerequisites\n", + "\n", + "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", + "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", + "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", + "\n", + "### Change Colab dark theme\n", + "\n", + "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", + "\n", + "![](https://i.imgur.com/EJ0GDP8.png)\n", + "\n", + "\n", + "### Install geemap\n", + "\n", + "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install -U \"geemap[workshop]\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", + "\n", + "```bash\n", + "conda create -n gee python=3.11\n", + "conda activate gee\n", + "conda install -c conda-forge mamba\n", + "mamba install -c conda-forge geemap pygis\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries\n", + "\n", + "Import the earthengine-api and geemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ee.Authenticate()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ee.Initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(basemap='Esri.WorldImagery')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('Esri.WorldTopoMap')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also change basemaps interactively using the basemap GUI." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", + "}\n", + "m.add_layer(image, vis_params, 'SRTM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "m.set_center(-73.9596, 40.7688, 12)\n", + "m.add_layer(fc, {}, 'Census roads')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "m.add_layer(fc, {}, 'Louisiana')\n", + "m.center_object(fc, 7)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "m.add_layer(fc, {}, 'West Coast')\n", + "m.center_object(fc, 5)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = m.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "m.add_layer(fc, {}, 'Southeastern U.S.')\n", + "m.center_object(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "m.add_layer(states.style(**style), {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "m.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "m.add_layer(dataset, {}, 'GAP CONUS')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import get_metadata\n", + "\n", + "get_metadata(DATA.USGS_GAP_CONUS_2011)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Converting Earth Engine JavaScripts to Python\n", + "\n", + "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load an image.\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", + "\n", + "# Define the visualization parameters.\n", + "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "# Center the map and display the image.\n", + "m.set_center(-122.1899, 37.5010, 10)\n", + "# San Francisco Bay\n", + "m.add_layer(image, vizParams, 'False color composite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/i3IT0lF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 1 (10 mins)\n", + "\n", + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_layer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m.add('inspector')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", + "m.add_plot_gui()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Landsat." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Hyperion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", + "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(add_google_map=False)\n", + "\n", + "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the color bar background transparent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\",\n", + " transparent_bg=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel map and linked maps\n", + "\n", + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", + "\n", + "m.split_map(left_layer, right_layer)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linked maps\n", + "\n", + "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = (\n", + " ee.ImageCollection('COPERNICUS/S2')\n", + " .filterDate('2018-09-01', '2018-09-30')\n", + " .map(lambda img: img.divide(10000))\n", + " .median()\n", + ")\n", + "\n", + "vis_params = [\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + "]\n", + "\n", + "labels = [\n", + " 'Natural Color (B4/B3/B2)',\n", + " 'Land/Water (B8/B11/B4)',\n", + " 'Color Infrared (B8/B4/B3)',\n", + " 'Vegetation (B12/B11/B4)',\n", + "]\n", + "\n", + "geemap.linked_maps(\n", + " rows=2,\n", + " cols=2,\n", + " height=\"300px\",\n", + " center=[38.4151, 21.2712],\n", + " zoom=12,\n", + " ee_objects=[image],\n", + " vis_params=vis_params,\n", + " labels=labels,\n", + " label_position=\"topright\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Timeseries inspector and time slider\n", + "\n", + "#### Timeseries inspector\n", + "\n", + "Check the available years of NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", + "vis_params = {'bands': ['landcover']}\n", + "years = collection.aggregate_array('system:index').getInfo()\n", + "years" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.ts_inspector(\n", + " left_ts=collection,\n", + " right_ts=collection,\n", + " left_names=years,\n", + " right_names=years,\n", + " left_vis=vis_params,\n", + " right_vis=vis_params,\n", + " width='80px',\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Time slider\n", + "\n", + "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", + "\n", + "Create a map for visualizing MODIS vegetation data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", + " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", + " .select(\"NDVI\")\n", + ")\n", + "vis_params = {\n", + " 'min': 0.0,\n", + " 'max': 1.0,\n", + " 'palette': 'ndvi',\n", + "}\n", + "\n", + "m.add_time_slider(collection, vis_params, time_interval=2)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a map for visualizing weather data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('NOAA/GFS0P25')\n", + " .filterDate('2018-12-22', '2018-12-23')\n", + " .limit(24)\n", + " .select('temperature_2m_above_ground')\n", + ")\n", + "\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "\n", + "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", + "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizing Sentinel-2 imagery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", + "\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", + " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", + ")\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "\n", + "m.add_time_slider(collection, vis_params)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "![](https://i.imgur.com/1b62CeI.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "m.center_object(centroid, 8)\n", + "m.add_layer(image, vis, \"Landsat-8\")\n", + "m.add_layer(centroid, {}, 'Centroid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = dataset.select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics with two images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dem = ee.Image('USGS/3DEP/10m')\n", + "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", + "m.add_layer(dem, vis, 'DEM')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computer the mean elevation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", + "stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats.to_csv('mean.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the standard deviation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df('std.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coordinate grids and fishnets\n", + "\n", + "#### Creating coordinate grids\n", + "\n", + "Create a latitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(lat_grid)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a longitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a rectangular grid with a 10-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = geemap.latlon_grid(\n", + " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating fishnets\n", + "\n", + "Create a fishnet based on an Earth Engine geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with a 2-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a new map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Draw a polygon on the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.Polygon(\n", + " [\n", + " [\n", + " [-64.602356, -1.127399],\n", + " [-68.821106, -12.625598],\n", + " [-60.647278, -22.498601],\n", + " [-47.815247, -21.111406],\n", + " [-43.860168, -8.913564],\n", + " [-54.582825, -0.775886],\n", + " [-60.823059, 0.454555],\n", + " [-64.602356, -1.127399],\n", + " ]\n", + " ]\n", + " )\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Land use and land cover change analysis\n", + "\n", + "#### Forest cover mapping\n", + "\n", + "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", + "dataset.bandNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", + "first_image = dataset.select(first_bands)\n", + "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", + "last_image = dataset.select(last_bands)\n", + "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the tree cover imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "treecover = dataset.select(['treecover2000'])\n", + "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", + "name = 'Tree cover (%)'\n", + "m.add_layer(treecover, treeCoverVisParam, name)\n", + "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract tree cover 2000 by using the threshold of 10%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "threshold = 10\n", + "treecover_bin = treecover.gte(threshold).selfMask()\n", + "treeVisParam = {'palette': ['green']}\n", + "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Forest loss and gain mapping\n", + "\n", + "Visualize forest loss." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss_year = dataset.select(['lossyear'])\n", + "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", + "layer_name = 'Tree loss year'\n", + "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", + "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare forest loss and gain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss = dataset.select(['loss']).selfMask()\n", + "treegain = dataset.select(['gain']).selfMask()\n", + "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", + "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by country\n", + "\n", + "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", + "\n", + "Add a country boundary layer to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", + "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", + "m.add_layer(countries.style(**style), {}, 'Countries')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treecover_bin,\n", + " countries,\n", + " 'forest_cover.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a pie chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart(\n", + " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'forest_cover.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treeloss.gt(0),\n", + " countries,\n", + " 'treeloss.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'treeloss.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest loss area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Analyzing forest cover gain and loss\n", + "\n", + "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", + "\n", + "![](https://i.imgur.com/NQ4UUnj.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 2 (10 mins)\n", + "\n", + "## Exporting Earth Engine data (30 mins)\n", + "\n", + "### Exporting images\n", + "\n", + "Add a Landsat image to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", + " ['B5', 'B4', 'B3']\n", + ")\n", + "\n", + "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "m.center_object(image)\n", + "m.add_layer(image, vis_params, 'Landsat')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a rectangle to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", + "fc = ee.FeatureCollection(region)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "m.add_layer(fc.style(**style), {}, 'ROI')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image projection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "projection = image.select(0).projection().getInfo()\n", + "projection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "crs = projection['crs']\n", + "crs_transform = projection['transform']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify region, crs, and crs_transform." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(\n", + " image,\n", + " filename=\"landsat_crs.tif\",\n", + " crs=crs,\n", + " crs_transform=crs_transform,\n", + " region=region,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_to_drive(\n", + " image, description='landsat', folder='export', region=region, scale=30\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "point = ee.Geometry.Point(-99.2222, 46.7816)\n", + "collection = (\n", + " ee.ImageCollection('USDA/NAIP/DOQQ')\n", + " .filterBounds(point)\n", + " .filterDate('2008-01-01', '2018-01-01')\n", + " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection.aggregate_array('system:index')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", + " ee.Filter.eq('country_na', 'Germany')\n", + ")\n", + "m.add_layer(fc, {}, \"Germany\")\n", + "m.center_object(fc)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector(fc, filename='Germany2.shp')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_geojson(fc, filename='Germany.geojson')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_csv(fc, filename='Germany.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdf = geemap.ee_to_gdf(fc)\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(fc)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector_to_drive(\n", + " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 5 - Exporting images by a fishnet\n", + "\n", + "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", + "\n", + "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", + "\n", + "![](https://i.imgur.com/L1IH3fq.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", + "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", + "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", + "m.add_layer(region, {}, 'ROI')\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", + "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " m.add_layer(roi, {}, 'ROI')\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", + "\n", + "![](https://i.imgur.com/ohrXeFC.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_gui(\"timelapse\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 3 (10 mins)\n", + "\n", + "## Building interactive web apps (30 mins)\n", + "\n", + "This section is optional. We might not have enough time to cover this section.\n", + "\n", + "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", + "\n", + "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", + "\n", + "After following the instructions above, you should have a web app that looks like this:\n", + "\n", + "![](https://i.imgur.com/X3ZFyRr.png)\n", + "\n", + "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/docs/workshops/GEE_Workshop_2021.ipynb b/docs/workshops/GEE_Workshop_2021.ipynb index 05f3ef9d0a..1c37b2b7d9 100644 --- a/docs/workshops/GEE_Workshop_2021.ipynb +++ b/docs/workshops/GEE_Workshop_2021.ipynb @@ -1065,7 +1065,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -1075,8 +1075,8 @@ "outputs": [], "source": [ "out_landsat_stats = os.path.join(out_dir, 'landsat_stats.csv')\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -1119,11 +1119,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -2766,4 +2766,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/GEE_Workshop_2022_Part2.ipynb b/docs/workshops/GEE_Workshop_2022_Part2.ipynb index ceda8374d5..277b3078af 100644 --- a/docs/workshops/GEE_Workshop_2022_Part2.ipynb +++ b/docs/workshops/GEE_Workshop_2022_Part2.ipynb @@ -620,7 +620,7 @@ " dataset,\n", " countries,\n", " 'esa_2021_country.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " scale=1000,\n", ")" @@ -865,7 +865,7 @@ " treecover_bin,\n", " countries,\n", " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " scale=1000,\n", ")" @@ -915,7 +915,7 @@ " treeloss,\n", " countries,\n", " 'treeloss.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " scale=1000,\n", ")" @@ -1158,4 +1158,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/GeoPython_2021.ipynb b/docs/workshops/GeoPython_2021.ipynb index 2e6c15374e..80494b0568 100644 --- a/docs/workshops/GeoPython_2021.ipynb +++ b/docs/workshops/GeoPython_2021.ipynb @@ -1028,7 +1028,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -1038,8 +1038,8 @@ "outputs": [], "source": [ "out_landsat_stats = os.path.join(out_dir, 'landsat_stats.csv')\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -1082,11 +1082,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -2737,4 +2737,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/Japan_2022.ipynb b/docs/workshops/Japan_2022.ipynb index bd8a12adcc..760efc2846 100644 --- a/docs/workshops/Japan_2022.ipynb +++ b/docs/workshops/Japan_2022.ipynb @@ -2025,7 +2025,7 @@ "source": [ "out_dem_stats = 'dem_stats.csv'\n", "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", ")" ] }, @@ -2040,7 +2040,7 @@ " landsat,\n", " states,\n", " out_landsat_stats,\n", - " statistics_type='MEAN',\n", + " stat_type='MEAN',\n", " scale=1000,\n", " return_fc=False,\n", ")" @@ -2088,7 +2088,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -2106,7 +2106,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", + " stat_type='PERCENTAGE',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -2978,4 +2978,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/NCSU_2023.ipynb b/docs/workshops/NCSU_2023.ipynb index 1d6da9b34e..b4c78f043a 100644 --- a/docs/workshops/NCSU_2023.ipynb +++ b/docs/workshops/NCSU_2023.ipynb @@ -1,1981 +1,1981 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", - "\n", - "**Interactive Cloud Computing with Google Earth Engine and geemap**\n", - "\n", - "- Notebook: \n", - "- Earth Engine: \n", - "- Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the workshop presented at the [GIS Week](https://www.gisweekatncstate.org/events-page) at North Carolina State University. \n", - "\n", - "### Abstract\n", - "\n", - "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", - "\n", - "### Prerequisites\n", - "\n", - "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", - "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", - "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", - "\n", - "### Change Colab dark theme\n", - "\n", - "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", - "\n", - "![](https://i.imgur.com/EJ0GDP8.png)\n", - "\n", - "\n", - "### Install geemap\n", - "\n", - "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install -U \"geemap[workshop]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", - "\n", - "```bash\n", - "conda create -n gee python=3.11\n", - "conda activate gee\n", - "conda install -c conda-forge mamba\n", - "mamba install -c conda-forge geemap pygis\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries\n", - "\n", - "Import the earthengine-api and geemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(basemap='Esri.WorldImagery')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('Esri.WorldTopoMap')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also change basemaps interactively using the basemap GUI." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", - "}\n", - "m.add_layer(image, vis_params, 'SRTM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "m.set_center(-73.9596, 40.7688, 12)\n", - "m.add_layer(fc, {}, 'Census roads')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "m.add_layer(fc, {}, 'Louisiana')\n", - "m.center_object(fc, 7)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "m.add_layer(fc, {}, 'West Coast')\n", - "m.center_object(fc, 5)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = m.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "m.add_layer(fc, {}, 'Southeastern U.S.')\n", - "m.center_object(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "m.add_layer(states.style(**style), {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "m.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "m.add_layer(dataset, {}, 'GAP CONUS')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery for a state of your choice for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/i3IT0lF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_layer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m.add('inspector')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", - "m.add_plot_gui()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Landsat." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Hyperion." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", - "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(add_google_map=False)\n", - "\n", - "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make the color bar background transparent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\",\n", - " transparent_bg=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", - "\n", - "m.split_map(left_layer, right_layer)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "![](https://i.imgur.com/1b62CeI.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "m.center_object(centroid, 8)\n", - "m.add_layer(image, vis, \"Landsat-8\")\n", - "m.add_layer(centroid, {}, 'Centroid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = dataset.select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", - "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " m.add_layer(roi, {}, 'ROI')\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", - "\n", - "![](https://i.imgur.com/ohrXeFC.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_gui(\"timelapse\")\n", - "m" - ] - } - ], - "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.11.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", + "\n", + "**Interactive Cloud Computing with Google Earth Engine and geemap**\n", + "\n", + "- Notebook: \n", + "- Earth Engine: \n", + "- Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the workshop presented at the [GIS Week](https://www.gisweekatncstate.org/events-page) at North Carolina State University. \n", + "\n", + "### Abstract\n", + "\n", + "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", + "\n", + "### Prerequisites\n", + "\n", + "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", + "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", + "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", + "\n", + "### Change Colab dark theme\n", + "\n", + "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", + "\n", + "![](https://i.imgur.com/EJ0GDP8.png)\n", + "\n", + "\n", + "### Install geemap\n", + "\n", + "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install -U \"geemap[workshop]\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", + "\n", + "```bash\n", + "conda create -n gee python=3.11\n", + "conda activate gee\n", + "conda install -c conda-forge mamba\n", + "mamba install -c conda-forge geemap pygis\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries\n", + "\n", + "Import the earthengine-api and geemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(basemap='Esri.WorldImagery')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('Esri.WorldTopoMap')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also change basemaps interactively using the basemap GUI." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", + "}\n", + "m.add_layer(image, vis_params, 'SRTM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "m.set_center(-73.9596, 40.7688, 12)\n", + "m.add_layer(fc, {}, 'Census roads')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "m.add_layer(fc, {}, 'Louisiana')\n", + "m.center_object(fc, 7)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "m.add_layer(fc, {}, 'West Coast')\n", + "m.center_object(fc, 5)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = m.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "m.add_layer(fc, {}, 'Southeastern U.S.')\n", + "m.center_object(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "m.add_layer(states.style(**style), {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "m.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "m.add_layer(dataset, {}, 'GAP CONUS')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery for a state of your choice for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/i3IT0lF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_layer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m.add('inspector')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", + "m.add_plot_gui()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Landsat." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Hyperion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", + "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(add_google_map=False)\n", + "\n", + "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the color bar background transparent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\",\n", + " transparent_bg=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", + "\n", + "m.split_map(left_layer, right_layer)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "![](https://i.imgur.com/1b62CeI.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "m.center_object(centroid, 8)\n", + "m.add_layer(image, vis, \"Landsat-8\")\n", + "m.add_layer(centroid, {}, 'Centroid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = dataset.select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", + "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " m.add_layer(roi, {}, 'ROI')\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", + "\n", + "![](https://i.imgur.com/ohrXeFC.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_gui(\"timelapse\")\n", + "m" + ] + } + ], + "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.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/docs/workshops/SRM_Workshop_2022.ipynb b/docs/workshops/SRM_Workshop_2022.ipynb index e2dbe722d8..37dfcd9173 100644 --- a/docs/workshops/SRM_Workshop_2022.ipynb +++ b/docs/workshops/SRM_Workshop_2022.ipynb @@ -1117,7 +1117,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -1127,8 +1127,8 @@ "outputs": [], "source": [ "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -1168,11 +1168,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -1607,4 +1607,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/docs/workshops/SciPy_2023.ipynb b/docs/workshops/SciPy_2023.ipynb index 4aa9087848..2939a7d794 100644 --- a/docs/workshops/SciPy_2023.ipynb +++ b/docs/workshops/SciPy_2023.ipynb @@ -1,3152 +1,3152 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", - "\n", - "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", - "\n", - "* Notebook: \n", - "* Earth Engine: \n", - "* Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the tutorial presented at the [SciPy 2023](https://www.scipy2023.org/) Conference by Qiusheng Wu and Steve Greenberg. Check out [this link](https://cfp.scipy.org/2023/talk/GQ7PG3/) for more information about the tutorial.\n", - "\n", - "### Abstract\n", - "\n", - "This tutorial is an introduction to cloud-based geospatial analysis with Earth Engine and the geemap Python package. We will cover the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment using geemap. We will also demonstrate how to develop and deploy interactive Earth Engine web apps. Throughout the session, practical examples and hands-on exercises will be provided to enhance learning. The attendees should have a basic understanding of Python and Jupyter Notebooks. Familiarity with Earth science and geospatial datasets is not required, but will be useful.\n", - "\n", - "\n", - "### Prerequisites\n", - "\n", - "To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "### Prior Python Programming Level of Knowledge Expected\n", - "\n", - "The attendees are expected to have a basic understanding of Python and Jupyter Notebook. Familiarity with Earth science and geospatial datasets is not necessary, but it will be helpful.\n", - "\n", - "### G4G Summit Tickets\n", - "\n", - "We offer two [Geo for Good (G4G) Summit](https://earthoutreachonair.withgoogle.com/events/geoforgood23) tickets to attendees of the EE SciPy workshop. The G4G Summit will be held on October 11-12, 2023, at the Google campus in Mountain View, CA. The link to express your interest in the tickets will be provided during the workshop. \n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,700 GitHub stars and is being used by over 900 projects on GitHub. \n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", - "\n", - "### Install geemap\n", - "\n", - "Uncomment the following line to install geemap if you are running this notebook in Google Colab." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install geemap[workshop]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.Map) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(basemap='Esri.WorldImagery')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "Map.addLayer(image, vis_params, 'SRTM')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "Map.setCenter(83.277, 17.7009, 12)\n", - "Map.addLayer(image, vis, 'Sentinel-2')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "Map.setCenter(83.277, 17.7009, 12)\n", - "Map.addLayer(image, vis, 'Sentinel-2')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "Map.setCenter(-73.9596, 40.7688, 12)\n", - "Map.addLayer(fc, {}, 'Census roads')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "Map.addLayer(fc, {}, 'Louisiana')\n", - "Map.centerObject(fc, 7)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "Map.addLayer(fc, {}, 'West Coast')\n", - "Map.centerObject(fc, 5)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = Map.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "Map.addLayer(fc, {}, 'Southeastern U.S.')\n", - "Map.centerObject(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "Map.addLayer(states, {}, \"US States\")\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "Map.addLayer(states.style(**style), {}, \"US States\")\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "Map.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of March 2023, the catalog contains over [1,000 datasets](https://github.com/samapriya/Earth-Engine-Datasets-List) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "Map.addLayer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "Map.addLayer(dataset, {}, 'GAP CONUS')\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import get_metadata\n", - "\n", - "get_metadata(DATA.USGS_GAP_CONUS_2011)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Converting Earth Engine JavaScripts to Python\n", - "\n", - "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load an image.\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", - "\n", - "# Define the visualization parameters.\n", - "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "# Center the map and display the image.\n", - "Map.setCenter(-122.1899, 37.5010, 10)\n", - "# San Francisco Bay\n", - "Map.addLayer(image, vizParams, 'False color composite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/DNIqGPY.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 1 (10 mins)\n", - "\n", - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", - "Map.addLayer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "Map.addLayer(states, {}, \"US States\")\n", - "Map.add_inspector()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "Map.addLayer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "Map.addLayer(hyperion, hyperion_vis, 'Hyperion')\n", - "Map.add_plot_gui()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map.add_basemap('Google Hybrid')\n", - "Map.add_basemap('NLCD 2019 CONUS Land Cover')\n", - "Map.add_legend(builtin_legend='NLCD', max_width='100px')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map.add_basemap('HYBRID')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", - "Map.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='460px'\n", - ")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(add_google_map=False)\n", - "\n", - "labels = ['One', 'Two', 'Three', 'Four', 'ect']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "Map.add_legend(labels=labels, colors=colors, position='bottomright')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map.add_basemap('Google Hybrid')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", - "Map.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", - "Map.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.add_colorbar(\n", - " vis_params, \n", - " label=\"Elevation (m)\", \n", - " layer_name=\"SRTM DEM\", \n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel map and linked maps\n", - "\n", - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.split_map(left_layer='Google Terrain', right_layer='OpenTopoMap')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2019')\n", - "\n", - "Map.split_map(left_layer, right_layer)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Linked maps\n", - "\n", - "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = (\n", - " ee.ImageCollection('COPERNICUS/S2')\n", - " .filterDate('2018-09-01', '2018-09-30')\n", - " .map(lambda img: img.divide(10000))\n", - " .median()\n", - ")\n", - "\n", - "vis_params = [\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - "]\n", - "\n", - "labels = [\n", - " 'Natural Color (B4/B3/B2)',\n", - " 'Land/Water (B8/B11/B4)',\n", - " 'Color Infrared (B8/B4/B3)',\n", - " 'Vegetation (B12/B11/B4)',\n", - "]\n", - "\n", - "geemap.linked_maps(\n", - " rows=2,\n", - " cols=2,\n", - " height=\"300px\",\n", - " center=[38.4151, 21.2712],\n", - " zoom=12,\n", - " ee_objects=[image],\n", - " vis_params=vis_params,\n", - " labels=labels,\n", - " label_position=\"topright\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Timeseries inspector and time slider\n", - "\n", - "#### Timeseries inspector\n", - "\n", - "Check the available years of NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", - "vis_params = {'bands': ['landcover']}\n", - "years = collection.aggregate_array('system:index').getInfo()\n", - "years" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a timeseries inspector for NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.ts_inspector(\n", - " left_ts=collection,\n", - " right_ts=collection,\n", - " left_names=years,\n", - " right_names=years,\n", - " left_vis=vis_params,\n", - " right_vis=vis_params,\n", - " width='80px',\n", - ")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Time slider\n", - "\n", - "Create a map for visualizing MODIS vegetation data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", - " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", - " .select(\"NDVI\")\n", - ")\n", - "vis_params = {\n", - " 'min': 0.0,\n", - " 'max': 1.0,\n", - " 'palette': 'ndvi',\n", - "}\n", - "\n", - "Map.add_time_slider(collection, vis_params, time_interval=2)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a map for visualizing weather data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('NOAA/GFS0P25')\n", - " .filterDate('2018-12-22', '2018-12-23')\n", - " .limit(24)\n", - " .select('temperature_2m_above_ground')\n", - ")\n", - "\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "\n", - "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", - "Map.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualizing Sentinel-2 imagery" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[37.75, -122.45], zoom=12)\n", - "\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", - " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", - ")\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "\n", - "Map.add_time_slider(collection, vis_params)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "\n", - "![](https://i.imgur.com/LJmztTd.png)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "Map.centerObject(centroid, 8)\n", - "Map.addLayer(image, vis, \"Landsat-8\")\n", - "Map.addLayer(centroid, {}, 'Centroid')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "Map.addLayer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "Map.addLayer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(states.style(**style), {}, 'US States')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", - "landcover = dataset.select('landcover')\n", - "Map.addLayer(landcover, {}, 'NLCD 2019')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "Map.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics with two images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by zone\n", - "\n", - "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "dem = ee.Image('USGS/3DEP/10m')\n", - "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", - "Map.addLayer(dem, vis, 'DEM')\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "landcover = ee.Image(\"USGS/NLCD_RELEASES/2019_REL/NLCD/2019\").select('landcover')\n", - "Map.addLayer(landcover, {}, 'NLCD 2019')\n", - "Map.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Computer the mean elevation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", - "stats" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats.to_csv('mean.csv', index=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute the standard deviation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df('std.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Coordinate grids and fishnets\n", - "\n", - "#### Creating coordinate grids\n", - "\n", - "Create a latitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(lat_grid.style(**style), {}, 'Latitude Grid')\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(lat_grid)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a longitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(lon_grid.style(**style), {}, 'Longitude Grid')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a rectangular grid with a 10-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grid = geemap.latlon_grid(\n", - " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(grid.style(**style), {}, 'Coordinate Grid')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating fishnets\n", - "\n", - "Create a fishnet based on an Earth Engine geometry." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", - " Map.addLayer(roi, {}, 'ROI')\n", - " Map.user_roi = None\n", - "\n", - "Map.centerObject(roi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with a 2-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a new map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Draw a polygon on the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.Polygon(\n", - " [\n", - " [\n", - " [-64.602356, -1.127399],\n", - " [-68.821106, -12.625598],\n", - " [-60.647278, -22.498601],\n", - " [-47.815247, -21.111406],\n", - " [-43.860168, -8.913564],\n", - " [-54.582825, -0.775886],\n", - " [-60.823059, 0.454555],\n", - " [-64.602356, -1.127399],\n", - " ]\n", - " ]\n", - " )\n", - " Map.addLayer(roi, {}, 'ROI')\n", - "\n", - "Map.centerObject(roi)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Land use and land cover change analysis\n", - "\n", - "#### Forest cover mapping\n", - "\n", - "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", - "dataset.bandNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", - "first_image = dataset.select(first_bands)\n", - "Map.addLayer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Year 2000 Bands 5/4/3')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2022." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", - "last_image = dataset.select(last_bands)\n", - "Map.addLayer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Year 2022 Bands 5/4/3')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the tree cover imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "treecover = dataset.select(['treecover2000'])\n", - "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", - "name = 'Tree cover (%)'\n", - "Map.addLayer(treecover, treeCoverVisParam, name)\n", - "Map.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extract tree cover 2000 by using the threshold of 10%." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 10\n", - "treecover_bin = treecover.gte(threshold).selfMask()\n", - "treeVisParam = {'palette': ['green']}\n", - "Map.addLayer(treecover_bin, treeVisParam, 'Tree cover bin')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Forest loss and gain mapping\n", - "\n", - "Visualize forest loss." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.add_basemap('Google Hybrid')\n", - "treeloss_year = dataset.select(['lossyear'])\n", - "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", - "layer_name = 'Tree loss year since 2000'\n", - "Map.addLayer(treeloss_year, treeLossVisParam, layer_name)\n", - "Map.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare forest loss and gain." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.add_basemap('Google Hybrid')\n", - "treeloss = dataset.select(['loss']).selfMask()\n", - "treegain = dataset.select(['gain']).selfMask()\n", - "Map.addLayer(treeloss, {'palette': 'red'}, 'Tree loss')\n", - "Map.addLayer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by country\n", - "\n", - "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", - "\n", - "Add a country boundary layer to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", - "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", - "Map.addLayer(countries.style(**style), {}, 'Countries')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treecover_bin,\n", - " countries,\n", - " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pie chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart(\n", - " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'forest_cover.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treeloss.gt(0),\n", - " countries,\n", - " 'treeloss.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'treeloss.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest loss area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Analyzing forest cover gain and loss\n", - "\n", - "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", - "\n", - "![](https://i.imgur.com/t5sH5ku.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 2 (10 mins)\n", - "\n", - "## Exporting Earth Engine data (30 mins)\n", - "\n", - "### Exporting images\n", - "\n", - "Add a Landsat image to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", - " ['B5', 'B4', 'B3']\n", - ")\n", - "\n", - "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "Map.centerObject(image)\n", - "Map.addLayer(image, vis_params, 'Landsat')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a rectangle to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", - "fc = ee.FeatureCollection(region)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "Map.addLayer(fc.style(**style), {}, 'ROI')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image projection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "projection = image.select(0).projection().getInfo()\n", - "projection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "crs = projection['crs']\n", - "crs_transform = projection['transform']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify region, crs, and crs_transform." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(\n", - " image,\n", - " filename=\"landsat_crs.tif\",\n", - " crs=crs,\n", - " crs_transform=crs_transform,\n", - " region=region,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_to_drive(\n", - " image, description='landsat', folder='export', region=region, scale=30\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "point = ee.Geometry.Point(-99.2222, 46.7816)\n", - "collection = (\n", - " ee.ImageCollection('USDA/NAIP/DOQQ')\n", - " .filterBounds(point)\n", - " .filterDate('2008-01-01', '2018-01-01')\n", - " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection.aggregate_array('system:index')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", - " ee.Filter.eq('country_na', 'Germany')\n", - ")\n", - "Map.addLayer(fc, {}, \"Germany\")\n", - "Map.centerObject(fc)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector(fc, filename='Germany2.shp')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_geojson(fc, filename='Germany.geojson')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_csv(fc, filename='Germany.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gdf = geemap.ee_to_gdf(fc)\n", - "gdf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(fc)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector_to_drive(\n", - " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5 - Exporting images by a fishnet\n", - "\n", - "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", - "\n", - "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", - "\n", - "![](https://i.imgur.com/L1IH3fq.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", - "Map.addLayer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", - "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", - "Map.addLayer(region, {}, 'ROI')\n", - "Map.centerObject(region)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(region, h_interval=4.0, v_interval=4.0, delta=0.5)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.download_ee_image_tiles(\n", - " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.download_ee_image_tiles_parallel(\n", - " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "## Creating Satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "\n", - "Map.addLayer(images, vis_params, \"Sentinel-2\", False)\n", - "Map.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "Map.centerObject(region)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " Map.addLayer(roi, {}, 'ROI')\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " Map.addLayer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "Map.addLayer(roi)\n", - "Map.centerObject(roi)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "Map.addLayer(roi)\n", - "Map.centerObject(roi)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/uFaXD9s.gif) example.\n", - "\n", - "![](https://i.imgur.com/vecPydF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.add_gui(\"timelapse\")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "## Break 3 (10 mins)\n", - "\n", - "## Building interactive web apps (30 mins)\n", - "\n", - "This section is optional. We might not have enough time to cover this section.\n", - "\n", - "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", - "\n", - "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", - "\n", - "After following the instructions above, you should have a web app that looks like this:\n", - "\n", - "![](https://i.imgur.com/uYDUPl0.png)\n", - "\n", - "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", + "\n", + "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", + "\n", + "* Notebook: \n", + "* Earth Engine: \n", + "* Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the tutorial presented at the [SciPy 2023](https://www.scipy2023.org/) Conference by Qiusheng Wu and Steve Greenberg. Check out [this link](https://cfp.scipy.org/2023/talk/GQ7PG3/) for more information about the tutorial.\n", + "\n", + "### Abstract\n", + "\n", + "This tutorial is an introduction to cloud-based geospatial analysis with Earth Engine and the geemap Python package. We will cover the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment using geemap. We will also demonstrate how to develop and deploy interactive Earth Engine web apps. Throughout the session, practical examples and hands-on exercises will be provided to enhance learning. The attendees should have a basic understanding of Python and Jupyter Notebooks. Familiarity with Earth science and geospatial datasets is not required, but will be useful.\n", + "\n", + "\n", + "### Prerequisites\n", + "\n", + "To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "### Prior Python Programming Level of Knowledge Expected\n", + "\n", + "The attendees are expected to have a basic understanding of Python and Jupyter Notebook. Familiarity with Earth science and geospatial datasets is not necessary, but it will be helpful.\n", + "\n", + "### G4G Summit Tickets\n", + "\n", + "We offer two [Geo for Good (G4G) Summit](https://earthoutreachonair.withgoogle.com/events/geoforgood23) tickets to attendees of the EE SciPy workshop. The G4G Summit will be held on October 11-12, 2023, at the Google campus in Mountain View, CA. The link to express your interest in the tickets will be provided during the workshop. \n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,700 GitHub stars and is being used by over 900 projects on GitHub. \n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", + "\n", + "### Install geemap\n", + "\n", + "Uncomment the following line to install geemap if you are running this notebook in Google Colab." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install geemap[workshop]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.Map) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(basemap='Esri.WorldImagery')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "Map.addLayer(image, vis_params, 'SRTM')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "Map.setCenter(83.277, 17.7009, 12)\n", + "Map.addLayer(image, vis, 'Sentinel-2')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "Map.setCenter(83.277, 17.7009, 12)\n", + "Map.addLayer(image, vis, 'Sentinel-2')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "Map.setCenter(-73.9596, 40.7688, 12)\n", + "Map.addLayer(fc, {}, 'Census roads')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "Map.addLayer(fc, {}, 'Louisiana')\n", + "Map.centerObject(fc, 7)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "Map.addLayer(fc, {}, 'West Coast')\n", + "Map.centerObject(fc, 5)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = Map.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "Map.addLayer(fc, {}, 'Southeastern U.S.')\n", + "Map.centerObject(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "Map.addLayer(states, {}, \"US States\")\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "Map.addLayer(states.style(**style), {}, \"US States\")\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "Map.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of March 2023, the catalog contains over [1,000 datasets](https://github.com/samapriya/Earth-Engine-Datasets-List) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "Map.addLayer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "Map.addLayer(dataset, {}, 'GAP CONUS')\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import get_metadata\n", + "\n", + "get_metadata(DATA.USGS_GAP_CONUS_2011)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Converting Earth Engine JavaScripts to Python\n", + "\n", + "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load an image.\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", + "\n", + "# Define the visualization parameters.\n", + "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "# Center the map and display the image.\n", + "Map.setCenter(-122.1899, 37.5010, 10)\n", + "# San Francisco Bay\n", + "Map.addLayer(image, vizParams, 'False color composite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/DNIqGPY.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 1 (10 mins)\n", + "\n", + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", + "Map.addLayer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "Map.addLayer(states, {}, \"US States\")\n", + "Map.add_inspector()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "Map.addLayer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "Map.addLayer(hyperion, hyperion_vis, 'Hyperion')\n", + "Map.add_plot_gui()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map.add_basemap('Google Hybrid')\n", + "Map.add_basemap('NLCD 2019 CONUS Land Cover')\n", + "Map.add_legend(builtin_legend='NLCD', max_width='100px')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map.add_basemap('HYBRID')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", + "Map.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='460px'\n", + ")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(add_google_map=False)\n", + "\n", + "labels = ['One', 'Two', 'Three', 'Four', 'ect']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "Map.add_legend(labels=labels, colors=colors, position='bottomright')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map.add_basemap('Google Hybrid')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", + "Map.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", + "Map.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.add_colorbar(\n", + " vis_params, \n", + " label=\"Elevation (m)\", \n", + " layer_name=\"SRTM DEM\", \n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel map and linked maps\n", + "\n", + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.split_map(left_layer='Google Terrain', right_layer='OpenTopoMap')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2019')\n", + "\n", + "Map.split_map(left_layer, right_layer)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linked maps\n", + "\n", + "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = (\n", + " ee.ImageCollection('COPERNICUS/S2')\n", + " .filterDate('2018-09-01', '2018-09-30')\n", + " .map(lambda img: img.divide(10000))\n", + " .median()\n", + ")\n", + "\n", + "vis_params = [\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + "]\n", + "\n", + "labels = [\n", + " 'Natural Color (B4/B3/B2)',\n", + " 'Land/Water (B8/B11/B4)',\n", + " 'Color Infrared (B8/B4/B3)',\n", + " 'Vegetation (B12/B11/B4)',\n", + "]\n", + "\n", + "geemap.linked_maps(\n", + " rows=2,\n", + " cols=2,\n", + " height=\"300px\",\n", + " center=[38.4151, 21.2712],\n", + " zoom=12,\n", + " ee_objects=[image],\n", + " vis_params=vis_params,\n", + " labels=labels,\n", + " label_position=\"topright\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Timeseries inspector and time slider\n", + "\n", + "#### Timeseries inspector\n", + "\n", + "Check the available years of NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", + "vis_params = {'bands': ['landcover']}\n", + "years = collection.aggregate_array('system:index').getInfo()\n", + "years" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a timeseries inspector for NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.ts_inspector(\n", + " left_ts=collection,\n", + " right_ts=collection,\n", + " left_names=years,\n", + " right_names=years,\n", + " left_vis=vis_params,\n", + " right_vis=vis_params,\n", + " width='80px',\n", + ")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Time slider\n", + "\n", + "Create a map for visualizing MODIS vegetation data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", + " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", + " .select(\"NDVI\")\n", + ")\n", + "vis_params = {\n", + " 'min': 0.0,\n", + " 'max': 1.0,\n", + " 'palette': 'ndvi',\n", + "}\n", + "\n", + "Map.add_time_slider(collection, vis_params, time_interval=2)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a map for visualizing weather data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('NOAA/GFS0P25')\n", + " .filterDate('2018-12-22', '2018-12-23')\n", + " .limit(24)\n", + " .select('temperature_2m_above_ground')\n", + ")\n", + "\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "\n", + "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", + "Map.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizing Sentinel-2 imagery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[37.75, -122.45], zoom=12)\n", + "\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", + " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", + ")\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "\n", + "Map.add_time_slider(collection, vis_params)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "\n", + "![](https://i.imgur.com/LJmztTd.png)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "Map.centerObject(centroid, 8)\n", + "Map.addLayer(image, vis, \"Landsat-8\")\n", + "Map.addLayer(centroid, {}, 'Centroid')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "Map.addLayer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "Map.addLayer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(states.style(**style), {}, 'US States')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", + "landcover = dataset.select('landcover')\n", + "Map.addLayer(landcover, {}, 'NLCD 2019')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "Map.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics with two images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by zone\n", + "\n", + "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "dem = ee.Image('USGS/3DEP/10m')\n", + "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", + "Map.addLayer(dem, vis, 'DEM')\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "landcover = ee.Image(\"USGS/NLCD_RELEASES/2019_REL/NLCD/2019\").select('landcover')\n", + "Map.addLayer(landcover, {}, 'NLCD 2019')\n", + "Map.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computer the mean elevation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", + "stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats.to_csv('mean.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the standard deviation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df('std.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coordinate grids and fishnets\n", + "\n", + "#### Creating coordinate grids\n", + "\n", + "Create a latitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(lat_grid.style(**style), {}, 'Latitude Grid')\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(lat_grid)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a longitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(lon_grid.style(**style), {}, 'Longitude Grid')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a rectangular grid with a 10-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = geemap.latlon_grid(\n", + " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(grid.style(**style), {}, 'Coordinate Grid')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating fishnets\n", + "\n", + "Create a fishnet based on an Earth Engine geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", + " Map.addLayer(roi, {}, 'ROI')\n", + " Map.user_roi = None\n", + "\n", + "Map.centerObject(roi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with a 2-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a new map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Draw a polygon on the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.Polygon(\n", + " [\n", + " [\n", + " [-64.602356, -1.127399],\n", + " [-68.821106, -12.625598],\n", + " [-60.647278, -22.498601],\n", + " [-47.815247, -21.111406],\n", + " [-43.860168, -8.913564],\n", + " [-54.582825, -0.775886],\n", + " [-60.823059, 0.454555],\n", + " [-64.602356, -1.127399],\n", + " ]\n", + " ]\n", + " )\n", + " Map.addLayer(roi, {}, 'ROI')\n", + "\n", + "Map.centerObject(roi)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Land use and land cover change analysis\n", + "\n", + "#### Forest cover mapping\n", + "\n", + "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", + "dataset.bandNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", + "first_image = dataset.select(first_bands)\n", + "Map.addLayer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Year 2000 Bands 5/4/3')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", + "last_image = dataset.select(last_bands)\n", + "Map.addLayer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Year 2022 Bands 5/4/3')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the tree cover imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "treecover = dataset.select(['treecover2000'])\n", + "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", + "name = 'Tree cover (%)'\n", + "Map.addLayer(treecover, treeCoverVisParam, name)\n", + "Map.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract tree cover 2000 by using the threshold of 10%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "threshold = 10\n", + "treecover_bin = treecover.gte(threshold).selfMask()\n", + "treeVisParam = {'palette': ['green']}\n", + "Map.addLayer(treecover_bin, treeVisParam, 'Tree cover bin')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Forest loss and gain mapping\n", + "\n", + "Visualize forest loss." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.add_basemap('Google Hybrid')\n", + "treeloss_year = dataset.select(['lossyear'])\n", + "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", + "layer_name = 'Tree loss year since 2000'\n", + "Map.addLayer(treeloss_year, treeLossVisParam, layer_name)\n", + "Map.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare forest loss and gain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.add_basemap('Google Hybrid')\n", + "treeloss = dataset.select(['loss']).selfMask()\n", + "treegain = dataset.select(['gain']).selfMask()\n", + "Map.addLayer(treeloss, {'palette': 'red'}, 'Tree loss')\n", + "Map.addLayer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by country\n", + "\n", + "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", + "\n", + "Add a country boundary layer to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", + "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", + "Map.addLayer(countries.style(**style), {}, 'Countries')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treecover_bin,\n", + " countries,\n", + " 'forest_cover.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a pie chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart(\n", + " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'forest_cover.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treeloss.gt(0),\n", + " countries,\n", + " 'treeloss.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'treeloss.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest loss area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Analyzing forest cover gain and loss\n", + "\n", + "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", + "\n", + "![](https://i.imgur.com/t5sH5ku.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 2 (10 mins)\n", + "\n", + "## Exporting Earth Engine data (30 mins)\n", + "\n", + "### Exporting images\n", + "\n", + "Add a Landsat image to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", + " ['B5', 'B4', 'B3']\n", + ")\n", + "\n", + "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "Map.centerObject(image)\n", + "Map.addLayer(image, vis_params, 'Landsat')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a rectangle to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", + "fc = ee.FeatureCollection(region)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "Map.addLayer(fc.style(**style), {}, 'ROI')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image projection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "projection = image.select(0).projection().getInfo()\n", + "projection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "crs = projection['crs']\n", + "crs_transform = projection['transform']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify region, crs, and crs_transform." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(\n", + " image,\n", + " filename=\"landsat_crs.tif\",\n", + " crs=crs,\n", + " crs_transform=crs_transform,\n", + " region=region,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_to_drive(\n", + " image, description='landsat', folder='export', region=region, scale=30\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "point = ee.Geometry.Point(-99.2222, 46.7816)\n", + "collection = (\n", + " ee.ImageCollection('USDA/NAIP/DOQQ')\n", + " .filterBounds(point)\n", + " .filterDate('2008-01-01', '2018-01-01')\n", + " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection.aggregate_array('system:index')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", + " ee.Filter.eq('country_na', 'Germany')\n", + ")\n", + "Map.addLayer(fc, {}, \"Germany\")\n", + "Map.centerObject(fc)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector(fc, filename='Germany2.shp')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_geojson(fc, filename='Germany.geojson')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_csv(fc, filename='Germany.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdf = geemap.ee_to_gdf(fc)\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(fc)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector_to_drive(\n", + " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 5 - Exporting images by a fishnet\n", + "\n", + "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", + "\n", + "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", + "\n", + "![](https://i.imgur.com/L1IH3fq.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", + "Map.addLayer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", + "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", + "Map.addLayer(region, {}, 'ROI')\n", + "Map.centerObject(region)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(region, h_interval=4.0, v_interval=4.0, delta=0.5)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.download_ee_image_tiles(\n", + " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.download_ee_image_tiles_parallel(\n", + " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## Creating Satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "\n", + "Map.addLayer(images, vis_params, \"Sentinel-2\", False)\n", + "Map.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "Map.centerObject(region)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " Map.addLayer(roi, {}, 'ROI')\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " Map.addLayer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "Map.addLayer(roi)\n", + "Map.centerObject(roi)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "Map.addLayer(roi)\n", + "Map.centerObject(roi)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/uFaXD9s.gif) example.\n", + "\n", + "![](https://i.imgur.com/vecPydF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.add_gui(\"timelapse\")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "## Break 3 (10 mins)\n", + "\n", + "## Building interactive web apps (30 mins)\n", + "\n", + "This section is optional. We might not have enough time to cover this section.\n", + "\n", + "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", + "\n", + "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", + "\n", + "After following the instructions above, you should have a web app that looks like this:\n", + "\n", + "![](https://i.imgur.com/uYDUPl0.png)\n", + "\n", + "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/examples/notebooks/00_geemap_colab.ipynb b/examples/notebooks/00_geemap_colab.ipynb index c8ed9734ce..9b6a1709b7 100644 --- a/examples/notebooks/00_geemap_colab.ipynb +++ b/examples/notebooks/00_geemap_colab.ipynb @@ -70,7 +70,6 @@ { "cell_type": "code", "execution_count": null, - "id": "3f36f050", "metadata": {}, "outputs": [], "source": [ diff --git a/examples/notebooks/12_zonal_statistics.ipynb b/examples/notebooks/12_zonal_statistics.ipynb index 4daa8c9f33..11a1ebe18b 100644 --- a/examples/notebooks/12_zonal_statistics.ipynb +++ b/examples/notebooks/12_zonal_statistics.ipynb @@ -91,7 +91,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -101,8 +101,8 @@ "outputs": [], "source": [ "out_landsat_stats = os.path.join(out_dir, 'landsat_stats.csv')\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -130,8 +130,12 @@ "display_name": "Python 3", "language": "python", "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.11.6" } }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/notebooks/131_arcgis.ipynb b/examples/notebooks/131_arcgis.ipynb index 0278f3f1b8..8d730d6197 100644 --- a/examples/notebooks/131_arcgis.ipynb +++ b/examples/notebooks/131_arcgis.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -20,7 +19,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -59,7 +57,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -84,7 +81,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/examples/notebooks/137_create_grid.ipynb b/examples/notebooks/137_create_grid.ipynb index 31e1bd8e27..8294632397 100644 --- a/examples/notebooks/137_create_grid.ipynb +++ b/examples/notebooks/137_create_grid.ipynb @@ -1,175 +1,175 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"Open\n", - "\n", - "**Creating a rectangular grid covering a region of interest for computing zonal statistics**\n", - "\n", - "Uncomment the following line to install [geemap](https://geemap.org) if needed." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install git+https://github.com/gee-community/geemap.git" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Import libraries" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Update the package and restart the kernel if you run into errors." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# geemap.update_package()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add temperature data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.ImageCollection('NOAA/GFS0P25').first().select('temperature_2m_above_ground')\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "Map.addLayer(image, vis_params, 'Temperature')\n", - "Map.add_colorbar(vis_params, label=\"Temperature (°C)\")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a grid covering the area of interest." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geometry = ee.Geometry.BBox(-130, 24, -68, 50)\n", - "grid = geemap.create_grid(geometry, 2e5)\n", - "Map.addLayer(grid, {}, 'Grid')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics based on the image and grid. In this case, we are computing the mean temperature for each grid cell." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.zonal_stats(\n", - " image, grid, statistics_type='MEAN', scale=2e5, return_fc=True\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add the mean temperature grid to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.add_styled_vector(\n", - " stats, column=\"mean\", palette='coolwarm', layer_name=\"Mean Temperature\"\n", - ")\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![](https://i.imgur.com/Kwe5eom.png)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"Open\n", + "\n", + "**Creating a rectangular grid covering a region of interest for computing zonal statistics**\n", + "\n", + "Uncomment the following line to install [geemap](https://geemap.org) if needed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install git+https://github.com/gee-community/geemap.git" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Update the package and restart the kernel if you run into errors." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# geemap.update_package()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add temperature data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.ImageCollection('NOAA/GFS0P25').first().select('temperature_2m_above_ground')\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "Map.addLayer(image, vis_params, 'Temperature')\n", + "Map.add_colorbar(vis_params, label=\"Temperature (°C)\")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a grid covering the area of interest." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geometry = ee.Geometry.BBox(-130, 24, -68, 50)\n", + "grid = geemap.create_grid(geometry, 2e5)\n", + "Map.addLayer(grid, {}, 'Grid')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics based on the image and grid. In this case, we are computing the mean temperature for each grid cell." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.zonal_stats(\n", + " image, grid, stat_type='MEAN', scale=2e5, return_fc=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add the mean temperature grid to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.add_styled_vector(\n", + " stats, column=\"mean\", palette='coolwarm', layer_name=\"Mean Temperature\"\n", + ")\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![](https://i.imgur.com/Kwe5eom.png)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/examples/notebooks/13_zonal_statistics_by_group.ipynb b/examples/notebooks/13_zonal_statistics_by_group.ipynb index 306d072023..111fcef373 100644 --- a/examples/notebooks/13_zonal_statistics_by_group.ipynb +++ b/examples/notebooks/13_zonal_statistics_by_group.ipynb @@ -97,11 +97,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilometers\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -211,11 +211,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " countries,\n", " global_stats,\n", - " statistics_type='PERCENTAGE',\n", + " stat_type='PERCENTAGE',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -240,4 +240,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/notebooks/58_add_vector.ipynb b/examples/notebooks/58_add_vector.ipynb index 03f91a37b5..13828a538b 100644 --- a/examples/notebooks/58_add_vector.ipynb +++ b/examples/notebooks/58_add_vector.ipynb @@ -126,7 +126,6 @@ { "cell_type": "code", "execution_count": null, - "id": "e1ddca8c", "metadata": {}, "outputs": [], "source": [ @@ -136,7 +135,6 @@ }, { "cell_type": "markdown", - "id": "e441583e", "metadata": {}, "source": [ "Uncomment to install `PyCRS` as needed" @@ -145,7 +143,6 @@ { "cell_type": "code", "execution_count": null, - "id": "d0b3cf80", "metadata": {}, "outputs": [], "source": [ diff --git a/examples/notebooks/63_charts.ipynb b/examples/notebooks/63_charts.ipynb index 1fd7eac630..cff5938b39 100644 --- a/examples/notebooks/63_charts.ipynb +++ b/examples/notebooks/63_charts.ipynb @@ -18,9 +18,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import ee\n", "import geemap\n", @@ -31,9 +66,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# geemap.update_package()" ] @@ -49,9 +119,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f66954a723f2433dbd376f43d391b26c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Map(center=[0, 0], controls=(WidgetControl(options=['position', 'transparent_bg'], widget=SearchDataGUI(childr…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "Map = geemap.Map()\n", "\n", @@ -65,9 +184,149 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01_tmean02_tmean03_tmean04_tmean05_tmean06_tmean07_tmean08_tmean09_tmean10_tmean11_tmean12_tmeanlabel
05.7910367.64501110.45465814.25164019.03281523.79050625.06657723.84525921.45479515.9979889.8493215.641386Desert
12.7924673.6090745.0329327.12013710.39537613.77613417.85017717.91998315.20657310.0817094.7847062.317886Forest
2-3.756608-1.9902202.5701467.72130613.64387519.03355822.75305921.84834616.4017709.2630212.021918-3.426706Grassland
\n", + "
" + ], + "text/plain": [ + " 01_tmean 02_tmean 03_tmean 04_tmean 05_tmean 06_tmean 07_tmean \\\n", + "0 5.791036 7.645011 10.454658 14.251640 19.032815 23.790506 25.066577 \n", + "1 2.792467 3.609074 5.032932 7.120137 10.395376 13.776134 17.850177 \n", + "2 -3.756608 -1.990220 2.570146 7.721306 13.643875 19.033558 22.753059 \n", + "\n", + " 08_tmean 09_tmean 10_tmean 11_tmean 12_tmean label \n", + "0 23.845259 21.454795 15.997988 9.849321 5.641386 Desert \n", + "1 17.919983 15.206573 10.081709 4.784706 2.317886 Forest \n", + "2 21.848346 16.401770 9.263021 2.021918 -3.426706 Grassland " + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df = geemap.ee_to_df(features)\n", "df" @@ -75,9 +334,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "xProperty = \"label\"\n", "yProperties = [str(x).zfill(2) + \"_tmean\" for x in range(1, 13)]\n", @@ -117,9 +411,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "options = {\n", " \"labels\": labels,\n", @@ -134,9 +463,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "42549b47340944a4a59a2bda020fd30d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Figure(axes=[Axis(label='Ecoregion', scale=OrdinalScale()), Axis(label='Temperature', orientati…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "chart.feature_byFeature(features, xProperty, yProperties, **options)" ] @@ -148,6 +526,785 @@ "![](https://i.imgur.com/9xzsUxg.png)" ] }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ecoregions = ee.FeatureCollection('projects/google/charts_feature_example')\n", + "normClim = ee.ImageCollection('OREGONSTATE/PRISM/Norm81m').toBands().select('[0-9][0-9]_tmean')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01_ppt01_tdmean01_tmax01_tmean01_tmin01_vpdmax01_vpdmin02_ppt02_tdmean02_tmax...12_ppt12_tdmean12_tmax12_tmean12_tmin12_vpdmax12_vpdminlabelvaluewarm
027.954341-5.93898114.0518545.791036-2.46978212.4875921.35483821.858469-5.51650816.323491...35.557367-5.75037513.8434685.641386-2.56069712.1732141.272226Desert01
1235.373540-0.6960756.5478292.792467-0.9628964.0987990.508449181.531780-0.7035668.196231...273.243438-0.6680415.8270722.317886-1.1913013.5216960.480811Forest11
29.636893-9.2439952.920941-3.756608-10.4341574.7509010.48778513.915104-7.8654284.853363...11.198115-8.8636833.177410-3.426706-10.0308225.0383560.488113Grassland20
\n", + "

3 rows × 87 columns

\n", + "
" + ], + "text/plain": [ + " 01_ppt 01_tdmean 01_tmax 01_tmean 01_tmin 01_vpdmax \\\n", + "0 27.954341 -5.938981 14.051854 5.791036 -2.469782 12.487592 \n", + "1 235.373540 -0.696075 6.547829 2.792467 -0.962896 4.098799 \n", + "2 9.636893 -9.243995 2.920941 -3.756608 -10.434157 4.750901 \n", + "\n", + " 01_vpdmin 02_ppt 02_tdmean 02_tmax ... 12_ppt 12_tdmean \\\n", + "0 1.354838 21.858469 -5.516508 16.323491 ... 35.557367 -5.750375 \n", + "1 0.508449 181.531780 -0.703566 8.196231 ... 273.243438 -0.668041 \n", + "2 0.487785 13.915104 -7.865428 4.853363 ... 11.198115 -8.863683 \n", + "\n", + " 12_tmax 12_tmean 12_tmin 12_vpdmax 12_vpdmin label value \\\n", + "0 13.843468 5.641386 -2.560697 12.173214 1.272226 Desert 0 \n", + "1 5.827072 2.317886 -1.191301 3.521696 0.480811 Forest 1 \n", + "2 3.177410 -3.426706 -10.030822 5.038356 0.488113 Grassland 2 \n", + "\n", + " warm \n", + "0 1 \n", + "1 1 \n", + "2 0 \n", + "\n", + "[3 rows x 87 columns]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "geemap.ee_to_df(ecoregions)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
    • type:Image
        • id:01_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:02_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:03_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:04_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:05_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:06_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:07_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:08_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:09_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:10_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:11_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
        • id:12_tmean
        • crs:GEOGCS[\"NAD83\", \n", + " DATUM[\"North_American_Datum_1983\", \n", + " SPHEROID[\"GRS_1980\", 6378137.0, 298.257222101]], \n", + " PRIMEM[\"Greenwich\", 0.0], \n", + " UNIT[\"degree\", 0.017453292519943295], \n", + " AXIS[\"Longitude\", EAST], \n", + " AXIS[\"Latitude\", NORTH]]
          • 0:0.041666666667
          • 1:0
          • 2:-125.0208333333335
          • 3:0
          • 4:-0.041666666667
          • 5:49.9375000000025
          • type:PixelType
          • precision:float
          • 0:1405
          • 1:621
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "normClim" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fc = geemap.zonal_stats(normClim, ecoregions, stat_type='MEAN', scale=500, return_fc=True, verbose=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01_ppt01_tdmean01_tmax01_tmean01_tmin01_vpdmax01_vpdmin02_ppt02_tdmean02_tmax...12_ppt12_tdmean12_tmax12_tmean12_tmin12_vpdmax12_vpdminlabelvaluewarm
027.954341-5.93898114.0518545.910990-2.46978212.4875921.35483821.858469-5.51650816.323491...35.557367-5.75037513.8434685.783772-2.56069712.1732141.272226Desert01
1235.373540-0.6960756.5478293.094200-0.9628964.0987990.508449181.531780-0.7035668.196231...273.243438-0.6680415.8270722.610459-1.1913013.5216960.480811Forest11
29.636893-9.2439952.920941-3.734058-10.4341574.7509010.48778513.915104-7.8654284.853363...11.198115-8.8636833.177410-3.396242-10.0308225.0383560.488113Grassland20
\n", + "

3 rows × 87 columns

\n", + "
" + ], + "text/plain": [ + " 01_ppt 01_tdmean 01_tmax 01_tmean 01_tmin 01_vpdmax \\\n", + "0 27.954341 -5.938981 14.051854 5.910990 -2.469782 12.487592 \n", + "1 235.373540 -0.696075 6.547829 3.094200 -0.962896 4.098799 \n", + "2 9.636893 -9.243995 2.920941 -3.734058 -10.434157 4.750901 \n", + "\n", + " 01_vpdmin 02_ppt 02_tdmean 02_tmax ... 12_ppt 12_tdmean \\\n", + "0 1.354838 21.858469 -5.516508 16.323491 ... 35.557367 -5.750375 \n", + "1 0.508449 181.531780 -0.703566 8.196231 ... 273.243438 -0.668041 \n", + "2 0.487785 13.915104 -7.865428 4.853363 ... 11.198115 -8.863683 \n", + "\n", + " 12_tmax 12_tmean 12_tmin 12_vpdmax 12_vpdmin label value \\\n", + "0 13.843468 5.783772 -2.560697 12.173214 1.272226 Desert 0 \n", + "1 5.827072 2.610459 -1.191301 3.521696 0.480811 Forest 1 \n", + "2 3.177410 -3.396242 -10.030822 5.038356 0.488113 Grassland 2 \n", + "\n", + " warm \n", + "0 1 \n", + "1 1 \n", + "2 0 \n", + "\n", + "[3 rows x 87 columns]" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "geemap.ee_to_df(fc)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -159,9 +1316,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "be0a3e6aa46e441eaa345ad6ea770d36", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Map(center=[0, 0], controls=(WidgetControl(options=['position', 'transparent_bg'], widget=SearchDataGUI(childr…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "Map = geemap.Map()\n", "\n", @@ -175,9 +1381,154 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01_ppt02_ppt03_ppt04_ppt05_ppt06_ppt07_ppt08_ppt09_ppt10_ppt11_ppt12_pptlabel
027.95434121.85846917.5791248.2525438.37221614.80212380.38940979.32688637.41224732.72869422.80909935.557367Desert
1235.373540181.531780181.917962150.759019112.39213972.70987723.40921625.39556654.064534121.976155261.008798273.243438Forest
29.63689313.91510429.76129557.73611284.27645086.13686076.18175560.18963045.83316138.13490720.08592311.198115Grassland
\n", + "
" + ], + "text/plain": [ + " 01_ppt 02_ppt 03_ppt 04_ppt 05_ppt 06_ppt \\\n", + "0 27.954341 21.858469 17.579124 8.252543 8.372216 14.802123 \n", + "1 235.373540 181.531780 181.917962 150.759019 112.392139 72.709877 \n", + "2 9.636893 13.915104 29.761295 57.736112 84.276450 86.136860 \n", + "\n", + " 07_ppt 08_ppt 09_ppt 10_ppt 11_ppt 12_ppt \\\n", + "0 80.389409 79.326886 37.412247 32.728694 22.809099 35.557367 \n", + "1 23.409216 25.395566 54.064534 121.976155 261.008798 273.243438 \n", + "2 76.181755 60.189630 45.833161 38.134907 20.085923 11.198115 \n", + "\n", + " label \n", + "0 Desert \n", + "1 Forest \n", + "2 Grassland " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df = geemap.ee_to_df(features)\n", "df" @@ -185,9 +1536,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "keys = [str(x).zfill(2) + \"_ppt\" for x in range(1, 13)]\n", "values = [\n", @@ -208,9 +1594,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "xProperties = dict(zip(keys, values))\n", "seriesProperty = \"label\"" @@ -218,9 +1639,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "options = {\n", " 'title': \"Average Ecoregion Precipitation by Month\",\n", @@ -234,9 +1690,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2ad49b761e9e413e8e1cdaf59294a9d7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Figure(axes=[Axis(label='Month', scale=OrdinalScale()), Axis(label='Precipitation (mm)', orient…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "chart.feature_byProperty(features, xProperties, seriesProperty, **options)" ] @@ -258,9 +1763,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "Map = geemap.Map()\n", "\n", @@ -272,9 +1812,44 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "options = {\n", " 'title': \"Average January Temperature by Ecoregion\",\n", @@ -289,9 +1864,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5455a0ff48e6453ca24e1738a3eeee5f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Figure(axes=[Axis(label='Ecoregion', scale=OrdinalScale()), Axis(label='Jan temp (C)', orientat…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "chart.feature_groups(features, xProperty, yProperty, seriesProperty, **options)" ] @@ -302,6 +1926,18 @@ "display_name": "Python 3", "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.6" } }, "nbformat": 4, diff --git a/examples/workshops/AGU_2023.ipynb b/examples/workshops/AGU_2023.ipynb index 3f27fb97c1..1a86f4fd98 100644 --- a/examples/workshops/AGU_2023.ipynb +++ b/examples/workshops/AGU_2023.ipynb @@ -1,3219 +1,3219 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", - "\n", - "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", - "\n", - "- Notebook: \n", - "- Earth Engine: \n", - "- Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the workshop presented at the [AGU Annual Meeting 2023](https://www.agu.org/fall-meeting).\n", - "\n", - "### Abstract\n", - "\n", - "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", - "\n", - "### Prerequisites\n", - "\n", - "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", - "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", - "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", - "\n", - "### Change Colab dark theme\n", - "\n", - "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", - "\n", - "![](https://i.imgur.com/EJ0GDP8.png)\n", - "\n", - "\n", - "### Install geemap\n", - "\n", - "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install -U \"geemap[workshop]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", - "\n", - "```bash\n", - "conda create -n gee python=3.11\n", - "conda activate gee\n", - "conda install -c conda-forge mamba\n", - "mamba install -c conda-forge geemap pygis\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries\n", - "\n", - "Import the earthengine-api and geemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(basemap='Esri.WorldImagery')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('Esri.WorldTopoMap')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also change basemaps interactively using the basemap GUI." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", - "}\n", - "m.add_layer(image, vis_params, 'SRTM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "m.set_center(-73.9596, 40.7688, 12)\n", - "m.add_layer(fc, {}, 'Census roads')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "m.add_layer(fc, {}, 'Louisiana')\n", - "m.center_object(fc, 7)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "m.add_layer(fc, {}, 'West Coast')\n", - "m.center_object(fc, 5)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = m.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "m.add_layer(fc, {}, 'Southeastern U.S.')\n", - "m.center_object(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "m.add_layer(states.style(**style), {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "m.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "m.add_layer(dataset, {}, 'GAP CONUS')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import get_metadata\n", - "\n", - "get_metadata(DATA.USGS_GAP_CONUS_2011)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Converting Earth Engine JavaScripts to Python\n", - "\n", - "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load an image.\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", - "\n", - "# Define the visualization parameters.\n", - "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "# Center the map and display the image.\n", - "m.set_center(-122.1899, 37.5010, 10)\n", - "# San Francisco Bay\n", - "m.add_layer(image, vizParams, 'False color composite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/i3IT0lF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 1 (10 mins)\n", - "\n", - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_layer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m.add('inspector')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", - "m.add_plot_gui()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Landsat." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Hyperion." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", - "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(add_google_map=False)\n", - "\n", - "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make the color bar background transparent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\",\n", - " transparent_bg=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel map and linked maps\n", - "\n", - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", - "\n", - "m.split_map(left_layer, right_layer)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Linked maps\n", - "\n", - "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = (\n", - " ee.ImageCollection('COPERNICUS/S2')\n", - " .filterDate('2018-09-01', '2018-09-30')\n", - " .map(lambda img: img.divide(10000))\n", - " .median()\n", - ")\n", - "\n", - "vis_params = [\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - "]\n", - "\n", - "labels = [\n", - " 'Natural Color (B4/B3/B2)',\n", - " 'Land/Water (B8/B11/B4)',\n", - " 'Color Infrared (B8/B4/B3)',\n", - " 'Vegetation (B12/B11/B4)',\n", - "]\n", - "\n", - "geemap.linked_maps(\n", - " rows=2,\n", - " cols=2,\n", - " height=\"300px\",\n", - " center=[38.4151, 21.2712],\n", - " zoom=12,\n", - " ee_objects=[image],\n", - " vis_params=vis_params,\n", - " labels=labels,\n", - " label_position=\"topright\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Timeseries inspector and time slider\n", - "\n", - "#### Timeseries inspector\n", - "\n", - "Check the available years of NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", - "vis_params = {'bands': ['landcover']}\n", - "years = collection.aggregate_array('system:index').getInfo()\n", - "years" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.ts_inspector(\n", - " left_ts=collection,\n", - " right_ts=collection,\n", - " left_names=years,\n", - " right_names=years,\n", - " left_vis=vis_params,\n", - " right_vis=vis_params,\n", - " width='80px',\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Time slider\n", - "\n", - "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", - "\n", - "Create a map for visualizing MODIS vegetation data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", - " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", - " .select(\"NDVI\")\n", - ")\n", - "vis_params = {\n", - " 'min': 0.0,\n", - " 'max': 1.0,\n", - " 'palette': 'ndvi',\n", - "}\n", - "\n", - "m.add_time_slider(collection, vis_params, time_interval=2)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a map for visualizing weather data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('NOAA/GFS0P25')\n", - " .filterDate('2018-12-22', '2018-12-23')\n", - " .limit(24)\n", - " .select('temperature_2m_above_ground')\n", - ")\n", - "\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "\n", - "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", - "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualizing Sentinel-2 imagery" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", - "\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", - " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", - ")\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "\n", - "m.add_time_slider(collection, vis_params)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "![](https://i.imgur.com/1b62CeI.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "m.center_object(centroid, 8)\n", - "m.add_layer(image, vis, \"Landsat-8\")\n", - "m.add_layer(centroid, {}, 'Centroid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = dataset.select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics with two images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dem = ee.Image('USGS/3DEP/10m')\n", - "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", - "m.add_layer(dem, vis, 'DEM')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Computer the mean elevation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", - "stats" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats.to_csv('mean.csv', index=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute the standard deviation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df('std.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Coordinate grids and fishnets\n", - "\n", - "#### Creating coordinate grids\n", - "\n", - "Create a latitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(lat_grid)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a longitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a rectangular grid with a 10-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grid = geemap.latlon_grid(\n", - " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating fishnets\n", - "\n", - "Create a fishnet based on an Earth Engine geometry." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with a 2-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a new map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Draw a polygon on the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.Polygon(\n", - " [\n", - " [\n", - " [-64.602356, -1.127399],\n", - " [-68.821106, -12.625598],\n", - " [-60.647278, -22.498601],\n", - " [-47.815247, -21.111406],\n", - " [-43.860168, -8.913564],\n", - " [-54.582825, -0.775886],\n", - " [-60.823059, 0.454555],\n", - " [-64.602356, -1.127399],\n", - " ]\n", - " ]\n", - " )\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Land use and land cover change analysis\n", - "\n", - "#### Forest cover mapping\n", - "\n", - "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", - "dataset.bandNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", - "first_image = dataset.select(first_bands)\n", - "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2022." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", - "last_image = dataset.select(last_bands)\n", - "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the tree cover imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "treecover = dataset.select(['treecover2000'])\n", - "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", - "name = 'Tree cover (%)'\n", - "m.add_layer(treecover, treeCoverVisParam, name)\n", - "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extract tree cover 2000 by using the threshold of 10%." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 10\n", - "treecover_bin = treecover.gte(threshold).selfMask()\n", - "treeVisParam = {'palette': ['green']}\n", - "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Forest loss and gain mapping\n", - "\n", - "Visualize forest loss." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss_year = dataset.select(['lossyear'])\n", - "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", - "layer_name = 'Tree loss year'\n", - "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", - "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare forest loss and gain." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss = dataset.select(['loss']).selfMask()\n", - "treegain = dataset.select(['gain']).selfMask()\n", - "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", - "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by country\n", - "\n", - "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", - "\n", - "Add a country boundary layer to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", - "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", - "m.add_layer(countries.style(**style), {}, 'Countries')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treecover_bin,\n", - " countries,\n", - " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pie chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart(\n", - " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'forest_cover.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treeloss.gt(0),\n", - " countries,\n", - " 'treeloss.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'treeloss.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest loss area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Analyzing forest cover gain and loss\n", - "\n", - "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", - "\n", - "![](https://i.imgur.com/NQ4UUnj.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 2 (10 mins)\n", - "\n", - "## Exporting Earth Engine data (30 mins)\n", - "\n", - "### Exporting images\n", - "\n", - "Add a Landsat image to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", - " ['B5', 'B4', 'B3']\n", - ")\n", - "\n", - "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "m.center_object(image)\n", - "m.add_layer(image, vis_params, 'Landsat')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a rectangle to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", - "fc = ee.FeatureCollection(region)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "m.add_layer(fc.style(**style), {}, 'ROI')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image projection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "projection = image.select(0).projection().getInfo()\n", - "projection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "crs = projection['crs']\n", - "crs_transform = projection['transform']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify region, crs, and crs_transform." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(\n", - " image,\n", - " filename=\"landsat_crs.tif\",\n", - " crs=crs,\n", - " crs_transform=crs_transform,\n", - " region=region,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_to_drive(\n", - " image, description='landsat', folder='export', region=region, scale=30\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "point = ee.Geometry.Point(-99.2222, 46.7816)\n", - "collection = (\n", - " ee.ImageCollection('USDA/NAIP/DOQQ')\n", - " .filterBounds(point)\n", - " .filterDate('2008-01-01', '2018-01-01')\n", - " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection.aggregate_array('system:index')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", - " ee.Filter.eq('country_na', 'Germany')\n", - ")\n", - "m.add_layer(fc, {}, \"Germany\")\n", - "m.center_object(fc)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector(fc, filename='Germany2.shp')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_geojson(fc, filename='Germany.geojson')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_csv(fc, filename='Germany.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gdf = geemap.ee_to_gdf(fc)\n", - "gdf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(fc)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector_to_drive(\n", - " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5 - Exporting images by a fishnet\n", - "\n", - "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", - "\n", - "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", - "\n", - "![](https://i.imgur.com/L1IH3fq.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", - "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", - "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", - "m.add_layer(region, {}, 'ROI')\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", - "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " m.add_layer(roi, {}, 'ROI')\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", - "\n", - "![](https://i.imgur.com/ohrXeFC.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_gui(\"timelapse\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 3 (10 mins)\n", - "\n", - "## Building interactive web apps (30 mins)\n", - "\n", - "This section is optional. We might not have enough time to cover this section.\n", - "\n", - "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", - "\n", - "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", - "\n", - "After following the instructions above, you should have a web app that looks like this:\n", - "\n", - "![](https://i.imgur.com/X3ZFyRr.png)\n", - "\n", - "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", + "\n", + "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", + "\n", + "- Notebook: \n", + "- Earth Engine: \n", + "- Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the workshop presented at the [AGU Annual Meeting 2023](https://www.agu.org/fall-meeting).\n", + "\n", + "### Abstract\n", + "\n", + "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", + "\n", + "### Prerequisites\n", + "\n", + "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", + "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", + "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/AGU_2023.ipynb)\n", + "\n", + "### Change Colab dark theme\n", + "\n", + "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", + "\n", + "![](https://i.imgur.com/EJ0GDP8.png)\n", + "\n", + "\n", + "### Install geemap\n", + "\n", + "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install -U \"geemap[workshop]\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", + "\n", + "```bash\n", + "conda create -n gee python=3.11\n", + "conda activate gee\n", + "conda install -c conda-forge mamba\n", + "mamba install -c conda-forge geemap pygis\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries\n", + "\n", + "Import the earthengine-api and geemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(basemap='Esri.WorldImagery')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('Esri.WorldTopoMap')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also change basemaps interactively using the basemap GUI." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", + "}\n", + "m.add_layer(image, vis_params, 'SRTM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "m.set_center(-73.9596, 40.7688, 12)\n", + "m.add_layer(fc, {}, 'Census roads')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "m.add_layer(fc, {}, 'Louisiana')\n", + "m.center_object(fc, 7)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "m.add_layer(fc, {}, 'West Coast')\n", + "m.center_object(fc, 5)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = m.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "m.add_layer(fc, {}, 'Southeastern U.S.')\n", + "m.center_object(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "m.add_layer(states.style(**style), {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "m.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "m.add_layer(dataset, {}, 'GAP CONUS')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import get_metadata\n", + "\n", + "get_metadata(DATA.USGS_GAP_CONUS_2011)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Converting Earth Engine JavaScripts to Python\n", + "\n", + "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load an image.\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", + "\n", + "# Define the visualization parameters.\n", + "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "# Center the map and display the image.\n", + "m.set_center(-122.1899, 37.5010, 10)\n", + "# San Francisco Bay\n", + "m.add_layer(image, vizParams, 'False color composite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/i3IT0lF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 1 (10 mins)\n", + "\n", + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_layer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m.add('inspector')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", + "m.add_plot_gui()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Landsat." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Hyperion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", + "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(add_google_map=False)\n", + "\n", + "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the color bar background transparent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\",\n", + " transparent_bg=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel map and linked maps\n", + "\n", + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", + "\n", + "m.split_map(left_layer, right_layer)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linked maps\n", + "\n", + "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = (\n", + " ee.ImageCollection('COPERNICUS/S2')\n", + " .filterDate('2018-09-01', '2018-09-30')\n", + " .map(lambda img: img.divide(10000))\n", + " .median()\n", + ")\n", + "\n", + "vis_params = [\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + "]\n", + "\n", + "labels = [\n", + " 'Natural Color (B4/B3/B2)',\n", + " 'Land/Water (B8/B11/B4)',\n", + " 'Color Infrared (B8/B4/B3)',\n", + " 'Vegetation (B12/B11/B4)',\n", + "]\n", + "\n", + "geemap.linked_maps(\n", + " rows=2,\n", + " cols=2,\n", + " height=\"300px\",\n", + " center=[38.4151, 21.2712],\n", + " zoom=12,\n", + " ee_objects=[image],\n", + " vis_params=vis_params,\n", + " labels=labels,\n", + " label_position=\"topright\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Timeseries inspector and time slider\n", + "\n", + "#### Timeseries inspector\n", + "\n", + "Check the available years of NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", + "vis_params = {'bands': ['landcover']}\n", + "years = collection.aggregate_array('system:index').getInfo()\n", + "years" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.ts_inspector(\n", + " left_ts=collection,\n", + " right_ts=collection,\n", + " left_names=years,\n", + " right_names=years,\n", + " left_vis=vis_params,\n", + " right_vis=vis_params,\n", + " width='80px',\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Time slider\n", + "\n", + "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", + "\n", + "Create a map for visualizing MODIS vegetation data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", + " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", + " .select(\"NDVI\")\n", + ")\n", + "vis_params = {\n", + " 'min': 0.0,\n", + " 'max': 1.0,\n", + " 'palette': 'ndvi',\n", + "}\n", + "\n", + "m.add_time_slider(collection, vis_params, time_interval=2)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a map for visualizing weather data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('NOAA/GFS0P25')\n", + " .filterDate('2018-12-22', '2018-12-23')\n", + " .limit(24)\n", + " .select('temperature_2m_above_ground')\n", + ")\n", + "\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "\n", + "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", + "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizing Sentinel-2 imagery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", + "\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", + " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", + ")\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "\n", + "m.add_time_slider(collection, vis_params)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "![](https://i.imgur.com/1b62CeI.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "m.center_object(centroid, 8)\n", + "m.add_layer(image, vis, \"Landsat-8\")\n", + "m.add_layer(centroid, {}, 'Centroid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = dataset.select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics with two images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dem = ee.Image('USGS/3DEP/10m')\n", + "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", + "m.add_layer(dem, vis, 'DEM')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computer the mean elevation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", + "stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats.to_csv('mean.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the standard deviation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df('std.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coordinate grids and fishnets\n", + "\n", + "#### Creating coordinate grids\n", + "\n", + "Create a latitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(lat_grid)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a longitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a rectangular grid with a 10-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = geemap.latlon_grid(\n", + " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating fishnets\n", + "\n", + "Create a fishnet based on an Earth Engine geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with a 2-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a new map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Draw a polygon on the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.Polygon(\n", + " [\n", + " [\n", + " [-64.602356, -1.127399],\n", + " [-68.821106, -12.625598],\n", + " [-60.647278, -22.498601],\n", + " [-47.815247, -21.111406],\n", + " [-43.860168, -8.913564],\n", + " [-54.582825, -0.775886],\n", + " [-60.823059, 0.454555],\n", + " [-64.602356, -1.127399],\n", + " ]\n", + " ]\n", + " )\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Land use and land cover change analysis\n", + "\n", + "#### Forest cover mapping\n", + "\n", + "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", + "dataset.bandNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", + "first_image = dataset.select(first_bands)\n", + "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", + "last_image = dataset.select(last_bands)\n", + "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the tree cover imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "treecover = dataset.select(['treecover2000'])\n", + "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", + "name = 'Tree cover (%)'\n", + "m.add_layer(treecover, treeCoverVisParam, name)\n", + "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract tree cover 2000 by using the threshold of 10%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "threshold = 10\n", + "treecover_bin = treecover.gte(threshold).selfMask()\n", + "treeVisParam = {'palette': ['green']}\n", + "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Forest loss and gain mapping\n", + "\n", + "Visualize forest loss." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss_year = dataset.select(['lossyear'])\n", + "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", + "layer_name = 'Tree loss year'\n", + "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", + "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare forest loss and gain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss = dataset.select(['loss']).selfMask()\n", + "treegain = dataset.select(['gain']).selfMask()\n", + "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", + "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by country\n", + "\n", + "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", + "\n", + "Add a country boundary layer to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", + "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", + "m.add_layer(countries.style(**style), {}, 'Countries')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treecover_bin,\n", + " countries,\n", + " 'forest_cover.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a pie chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart(\n", + " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'forest_cover.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treeloss.gt(0),\n", + " countries,\n", + " 'treeloss.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'treeloss.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest loss area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Analyzing forest cover gain and loss\n", + "\n", + "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", + "\n", + "![](https://i.imgur.com/NQ4UUnj.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 2 (10 mins)\n", + "\n", + "## Exporting Earth Engine data (30 mins)\n", + "\n", + "### Exporting images\n", + "\n", + "Add a Landsat image to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", + " ['B5', 'B4', 'B3']\n", + ")\n", + "\n", + "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "m.center_object(image)\n", + "m.add_layer(image, vis_params, 'Landsat')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a rectangle to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", + "fc = ee.FeatureCollection(region)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "m.add_layer(fc.style(**style), {}, 'ROI')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image projection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "projection = image.select(0).projection().getInfo()\n", + "projection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "crs = projection['crs']\n", + "crs_transform = projection['transform']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify region, crs, and crs_transform." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(\n", + " image,\n", + " filename=\"landsat_crs.tif\",\n", + " crs=crs,\n", + " crs_transform=crs_transform,\n", + " region=region,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_to_drive(\n", + " image, description='landsat', folder='export', region=region, scale=30\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "point = ee.Geometry.Point(-99.2222, 46.7816)\n", + "collection = (\n", + " ee.ImageCollection('USDA/NAIP/DOQQ')\n", + " .filterBounds(point)\n", + " .filterDate('2008-01-01', '2018-01-01')\n", + " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection.aggregate_array('system:index')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", + " ee.Filter.eq('country_na', 'Germany')\n", + ")\n", + "m.add_layer(fc, {}, \"Germany\")\n", + "m.center_object(fc)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector(fc, filename='Germany2.shp')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_geojson(fc, filename='Germany.geojson')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_csv(fc, filename='Germany.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdf = geemap.ee_to_gdf(fc)\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(fc)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector_to_drive(\n", + " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 5 - Exporting images by a fishnet\n", + "\n", + "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", + "\n", + "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", + "\n", + "![](https://i.imgur.com/L1IH3fq.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", + "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", + "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", + "m.add_layer(region, {}, 'ROI')\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", + "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " m.add_layer(roi, {}, 'ROI')\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", + "\n", + "![](https://i.imgur.com/ohrXeFC.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_gui(\"timelapse\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 3 (10 mins)\n", + "\n", + "## Building interactive web apps (30 mins)\n", + "\n", + "This section is optional. We might not have enough time to cover this section.\n", + "\n", + "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", + "\n", + "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", + "\n", + "After following the instructions above, you should have a web app that looks like this:\n", + "\n", + "![](https://i.imgur.com/X3ZFyRr.png)\n", + "\n", + "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/examples/workshops/AmericaView_2023.ipynb b/examples/workshops/AmericaView_2023.ipynb index 448e5f033d..7a9689557c 100644 --- a/examples/workshops/AmericaView_2023.ipynb +++ b/examples/workshops/AmericaView_2023.ipynb @@ -1167,7 +1167,7 @@ "source": [ "out_dem_stats = 'dem_stats.csv'\n", "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", ")" ] }, @@ -1182,7 +1182,7 @@ " landsat,\n", " states,\n", " out_landsat_stats,\n", - " statistics_type='MEAN',\n", + " stat_type='MEAN',\n", " scale=1000,\n", " return_fc=False,\n", ")" @@ -1230,7 +1230,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -1248,7 +1248,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", + " stat_type='PERCENTAGE',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -1997,4 +1997,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/Crop_Mapping_2022.ipynb b/examples/workshops/Crop_Mapping_2022.ipynb index ecc0d157f7..222d6dc7c2 100644 --- a/examples/workshops/Crop_Mapping_2022.ipynb +++ b/examples/workshops/Crop_Mapping_2022.ipynb @@ -256,7 +256,7 @@ "outputs": [], "source": [ "geemap.zonal_stats(\n", - " cropland, africa, 'esa_cropland.csv', statistics_type='SUM', scale=1000\n", + " cropland, africa, 'esa_cropland.csv', stat_type='SUM', scale=1000\n", ")" ] }, @@ -447,7 +447,7 @@ "outputs": [], "source": [ "geemap.zonal_stats(\n", - " cropland_ts, africa, 'esri_cropland.csv', statistics_type='SUM', scale=1000\n", + " cropland_ts, africa, 'esri_cropland.csv', stat_type='SUM', scale=1000\n", ")" ] }, @@ -519,7 +519,7 @@ " cropland_gain,\n", " countries,\n", " 'esri_cropland_gain.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " scale=1000,\n", ")" ] @@ -572,7 +572,7 @@ " cropland_loss,\n", " countries,\n", " 'esri_cropland_loss.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " scale=1000,\n", ")" ] @@ -733,4 +733,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/G4G_2023.ipynb b/examples/workshops/G4G_2023.ipynb index bdec022c67..c8080b8cd1 100644 --- a/examples/workshops/G4G_2023.ipynb +++ b/examples/workshops/G4G_2023.ipynb @@ -1,3235 +1,3235 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", - "\n", - "**Introduction to Google Earth Engine in Python**\n", - "\n", - "- Notebook: \n", - "- Earth Engine: \n", - "- Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the workshop presented at the [Geo for Good Summit 2023](https://earthoutreachonair.withgoogle.com/events/geoforgood23). Check out [this link](https://earthoutreachonair.withgoogle.com/events/geoforgood23?tab=g4gagenda&expand=module:agenda) for more information about the workshop.\n", - "\n", - "### Abstract\n", - "\n", - "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", - "\n", - "### Prerequisites\n", - "\n", - "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", - "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", - "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", - "\n", - "### Change Colab dark theme\n", - "\n", - "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", - "\n", - "![](https://i.imgur.com/EJ0GDP8.png)\n", - "\n", - "\n", - "### Install geemap\n", - "\n", - "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install -U \"geemap[workshop]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", - "\n", - "```bash\n", - "conda create -n gee python=3.11\n", - "conda activate gee\n", - "conda install -c conda-forge mamba\n", - "mamba install -c conda-forge geemap pygis\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries\n", - "\n", - "Import the earthengine-api and geemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ee.Authenticate()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ee.Initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(basemap='Esri.WorldImagery')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('Esri.WorldTopoMap')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also change basemaps interactively using the basemap GUI." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", - "}\n", - "m.add_layer(image, vis_params, 'SRTM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "m.set_center(-73.9596, 40.7688, 12)\n", - "m.add_layer(fc, {}, 'Census roads')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "m.add_layer(fc, {}, 'Louisiana')\n", - "m.center_object(fc, 7)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "m.add_layer(fc, {}, 'West Coast')\n", - "m.center_object(fc, 5)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = m.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "m.add_layer(fc, {}, 'Southeastern U.S.')\n", - "m.center_object(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "m.add_layer(states.style(**style), {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "m.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "m.add_layer(dataset, {}, 'GAP CONUS')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import get_metadata\n", - "\n", - "get_metadata(DATA.USGS_GAP_CONUS_2011)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Converting Earth Engine JavaScripts to Python\n", - "\n", - "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load an image.\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", - "\n", - "# Define the visualization parameters.\n", - "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "# Center the map and display the image.\n", - "m.set_center(-122.1899, 37.5010, 10)\n", - "# San Francisco Bay\n", - "m.add_layer(image, vizParams, 'False color composite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/i3IT0lF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 1 (10 mins)\n", - "\n", - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_layer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m.add('inspector')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", - "m.add_plot_gui()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Landsat." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Hyperion." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", - "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(add_google_map=False)\n", - "\n", - "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make the color bar background transparent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\",\n", - " transparent_bg=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel map and linked maps\n", - "\n", - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", - "\n", - "m.split_map(left_layer, right_layer)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Linked maps\n", - "\n", - "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = (\n", - " ee.ImageCollection('COPERNICUS/S2')\n", - " .filterDate('2018-09-01', '2018-09-30')\n", - " .map(lambda img: img.divide(10000))\n", - " .median()\n", - ")\n", - "\n", - "vis_params = [\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - "]\n", - "\n", - "labels = [\n", - " 'Natural Color (B4/B3/B2)',\n", - " 'Land/Water (B8/B11/B4)',\n", - " 'Color Infrared (B8/B4/B3)',\n", - " 'Vegetation (B12/B11/B4)',\n", - "]\n", - "\n", - "geemap.linked_maps(\n", - " rows=2,\n", - " cols=2,\n", - " height=\"300px\",\n", - " center=[38.4151, 21.2712],\n", - " zoom=12,\n", - " ee_objects=[image],\n", - " vis_params=vis_params,\n", - " labels=labels,\n", - " label_position=\"topright\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Timeseries inspector and time slider\n", - "\n", - "#### Timeseries inspector\n", - "\n", - "Check the available years of NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", - "vis_params = {'bands': ['landcover']}\n", - "years = collection.aggregate_array('system:index').getInfo()\n", - "years" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.ts_inspector(\n", - " left_ts=collection,\n", - " right_ts=collection,\n", - " left_names=years,\n", - " right_names=years,\n", - " left_vis=vis_params,\n", - " right_vis=vis_params,\n", - " width='80px',\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Time slider\n", - "\n", - "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", - "\n", - "Create a map for visualizing MODIS vegetation data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", - " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", - " .select(\"NDVI\")\n", - ")\n", - "vis_params = {\n", - " 'min': 0.0,\n", - " 'max': 1.0,\n", - " 'palette': 'ndvi',\n", - "}\n", - "\n", - "m.add_time_slider(collection, vis_params, time_interval=2)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a map for visualizing weather data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('NOAA/GFS0P25')\n", - " .filterDate('2018-12-22', '2018-12-23')\n", - " .limit(24)\n", - " .select('temperature_2m_above_ground')\n", - ")\n", - "\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "\n", - "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", - "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualizing Sentinel-2 imagery" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", - "\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", - " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", - ")\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "\n", - "m.add_time_slider(collection, vis_params)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "![](https://i.imgur.com/1b62CeI.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "m.center_object(centroid, 8)\n", - "m.add_layer(image, vis, \"Landsat-8\")\n", - "m.add_layer(centroid, {}, 'Centroid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = dataset.select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics with two images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dem = ee.Image('USGS/3DEP/10m')\n", - "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", - "m.add_layer(dem, vis, 'DEM')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Computer the mean elevation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", - "stats" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats.to_csv('mean.csv', index=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute the standard deviation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df('std.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Coordinate grids and fishnets\n", - "\n", - "#### Creating coordinate grids\n", - "\n", - "Create a latitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(lat_grid)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a longitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a rectangular grid with a 10-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grid = geemap.latlon_grid(\n", - " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating fishnets\n", - "\n", - "Create a fishnet based on an Earth Engine geometry." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with a 2-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a new map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Draw a polygon on the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.Polygon(\n", - " [\n", - " [\n", - " [-64.602356, -1.127399],\n", - " [-68.821106, -12.625598],\n", - " [-60.647278, -22.498601],\n", - " [-47.815247, -21.111406],\n", - " [-43.860168, -8.913564],\n", - " [-54.582825, -0.775886],\n", - " [-60.823059, 0.454555],\n", - " [-64.602356, -1.127399],\n", - " ]\n", - " ]\n", - " )\n", - " m.add_layer(roi, {}, 'ROI')\n", - "\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Land use and land cover change analysis\n", - "\n", - "#### Forest cover mapping\n", - "\n", - "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", - "dataset.bandNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", - "first_image = dataset.select(first_bands)\n", - "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2022." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", - "last_image = dataset.select(last_bands)\n", - "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the tree cover imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "treecover = dataset.select(['treecover2000'])\n", - "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", - "name = 'Tree cover (%)'\n", - "m.add_layer(treecover, treeCoverVisParam, name)\n", - "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extract tree cover 2000 by using the threshold of 10%." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 10\n", - "treecover_bin = treecover.gte(threshold).selfMask()\n", - "treeVisParam = {'palette': ['green']}\n", - "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Forest loss and gain mapping\n", - "\n", - "Visualize forest loss." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss_year = dataset.select(['lossyear'])\n", - "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", - "layer_name = 'Tree loss year'\n", - "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", - "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare forest loss and gain." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_basemap('Esri.WorldImagery')\n", - "treeloss = dataset.select(['loss']).selfMask()\n", - "treegain = dataset.select(['gain']).selfMask()\n", - "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", - "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", - "m.add('layer_manager')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by country\n", - "\n", - "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", - "\n", - "Add a country boundary layer to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", - "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", - "m.add_layer(countries.style(**style), {}, 'Countries')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treecover_bin,\n", - " countries,\n", - " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pie chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart(\n", - " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'forest_cover.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treeloss.gt(0),\n", - " countries,\n", - " 'treeloss.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'treeloss.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest loss area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Analyzing forest cover gain and loss\n", - "\n", - "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", - "\n", - "![](https://i.imgur.com/NQ4UUnj.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 2 (10 mins)\n", - "\n", - "## Exporting Earth Engine data (30 mins)\n", - "\n", - "### Exporting images\n", - "\n", - "Add a Landsat image to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", - " ['B5', 'B4', 'B3']\n", - ")\n", - "\n", - "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "m.center_object(image)\n", - "m.add_layer(image, vis_params, 'Landsat')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a rectangle to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", - "fc = ee.FeatureCollection(region)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "m.add_layer(fc.style(**style), {}, 'ROI')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image projection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "projection = image.select(0).projection().getInfo()\n", - "projection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "crs = projection['crs']\n", - "crs_transform = projection['transform']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify region, crs, and crs_transform." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(\n", - " image,\n", - " filename=\"landsat_crs.tif\",\n", - " crs=crs,\n", - " crs_transform=crs_transform,\n", - " region=region,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_to_drive(\n", - " image, description='landsat', folder='export', region=region, scale=30\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "point = ee.Geometry.Point(-99.2222, 46.7816)\n", - "collection = (\n", - " ee.ImageCollection('USDA/NAIP/DOQQ')\n", - " .filterBounds(point)\n", - " .filterDate('2008-01-01', '2018-01-01')\n", - " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection.aggregate_array('system:index')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", - " ee.Filter.eq('country_na', 'Germany')\n", - ")\n", - "m.add_layer(fc, {}, \"Germany\")\n", - "m.center_object(fc)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector(fc, filename='Germany2.shp')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_geojson(fc, filename='Germany.geojson')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_csv(fc, filename='Germany.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gdf = geemap.ee_to_gdf(fc)\n", - "gdf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(fc)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector_to_drive(\n", - " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5 - Exporting images by a fishnet\n", - "\n", - "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", - "\n", - "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", - "\n", - "![](https://i.imgur.com/L1IH3fq.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", - "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", - "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", - "m.add_layer(region, {}, 'ROI')\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", - "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " m.add_layer(roi, {}, 'ROI')\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", - "\n", - "![](https://i.imgur.com/ohrXeFC.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_gui(\"timelapse\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 3 (10 mins)\n", - "\n", - "## Building interactive web apps (30 mins)\n", - "\n", - "This section is optional. We might not have enough time to cover this section.\n", - "\n", - "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", - "\n", - "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", - "\n", - "After following the instructions above, you should have a web app that looks like this:\n", - "\n", - "![](https://i.imgur.com/X3ZFyRr.png)\n", - "\n", - "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.11.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", + "\n", + "**Introduction to Google Earth Engine in Python**\n", + "\n", + "- Notebook: \n", + "- Earth Engine: \n", + "- Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the workshop presented at the [Geo for Good Summit 2023](https://earthoutreachonair.withgoogle.com/events/geoforgood23). Check out [this link](https://earthoutreachonair.withgoogle.com/events/geoforgood23?tab=g4gagenda&expand=module:agenda) for more information about the workshop.\n", + "\n", + "### Abstract\n", + "\n", + "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. In addition, attendees will learn how to develop and deploy interactive Earth Engine web apps with Python. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab with the instructors. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", + "\n", + "### Prerequisites\n", + "\n", + "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", + "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", + "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/G4G_2023.ipynb)\n", + "\n", + "### Change Colab dark theme\n", + "\n", + "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", + "\n", + "![](https://i.imgur.com/EJ0GDP8.png)\n", + "\n", + "\n", + "### Install geemap\n", + "\n", + "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install -U \"geemap[workshop]\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", + "\n", + "```bash\n", + "conda create -n gee python=3.11\n", + "conda activate gee\n", + "conda install -c conda-forge mamba\n", + "mamba install -c conda-forge geemap pygis\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries\n", + "\n", + "Import the earthengine-api and geemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ee.Authenticate()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ee.Initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(basemap='Esri.WorldImagery')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('Esri.WorldTopoMap')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also change basemaps interactively using the basemap GUI." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", + "}\n", + "m.add_layer(image, vis_params, 'SRTM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "m.set_center(-73.9596, 40.7688, 12)\n", + "m.add_layer(fc, {}, 'Census roads')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "m.add_layer(fc, {}, 'Louisiana')\n", + "m.center_object(fc, 7)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "m.add_layer(fc, {}, 'West Coast')\n", + "m.center_object(fc, 5)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = m.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "m.add_layer(fc, {}, 'Southeastern U.S.')\n", + "m.center_object(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "m.add_layer(states.style(**style), {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "m.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "m.add_layer(dataset, {}, 'GAP CONUS')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import get_metadata\n", + "\n", + "get_metadata(DATA.USGS_GAP_CONUS_2011)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Converting Earth Engine JavaScripts to Python\n", + "\n", + "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load an image.\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", + "\n", + "# Define the visualization parameters.\n", + "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "# Center the map and display the image.\n", + "m.set_center(-122.1899, 37.5010, 10)\n", + "# San Francisco Bay\n", + "m.add_layer(image, vizParams, 'False color composite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/i3IT0lF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 1 (10 mins)\n", + "\n", + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_layer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m.add('inspector')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", + "m.add_plot_gui()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Landsat." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Hyperion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", + "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(add_google_map=False)\n", + "\n", + "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the color bar background transparent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\",\n", + " transparent_bg=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel map and linked maps\n", + "\n", + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", + "\n", + "m.split_map(left_layer, right_layer)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linked maps\n", + "\n", + "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations. Note that this feature does not work properly with Colab. Panning one map would not pan other maps. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = (\n", + " ee.ImageCollection('COPERNICUS/S2')\n", + " .filterDate('2018-09-01', '2018-09-30')\n", + " .map(lambda img: img.divide(10000))\n", + " .median()\n", + ")\n", + "\n", + "vis_params = [\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + "]\n", + "\n", + "labels = [\n", + " 'Natural Color (B4/B3/B2)',\n", + " 'Land/Water (B8/B11/B4)',\n", + " 'Color Infrared (B8/B4/B3)',\n", + " 'Vegetation (B12/B11/B4)',\n", + "]\n", + "\n", + "geemap.linked_maps(\n", + " rows=2,\n", + " cols=2,\n", + " height=\"300px\",\n", + " center=[38.4151, 21.2712],\n", + " zoom=12,\n", + " ee_objects=[image],\n", + " vis_params=vis_params,\n", + " labels=labels,\n", + " label_position=\"topright\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Timeseries inspector and time slider\n", + "\n", + "#### Timeseries inspector\n", + "\n", + "Check the available years of NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", + "vis_params = {'bands': ['landcover']}\n", + "years = collection.aggregate_array('system:index').getInfo()\n", + "years" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a timeseries inspector for NLCD. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.ts_inspector(\n", + " left_ts=collection,\n", + " right_ts=collection,\n", + " left_names=years,\n", + " right_names=years,\n", + " left_vis=vis_params,\n", + " right_vis=vis_params,\n", + " width='80px',\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Time slider\n", + "\n", + "Note that this feature may not work properly with Colab. Restart Colab runtime if the time slider does not work.\n", + "\n", + "Create a map for visualizing MODIS vegetation data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", + " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", + " .select(\"NDVI\")\n", + ")\n", + "vis_params = {\n", + " 'min': 0.0,\n", + " 'max': 1.0,\n", + " 'palette': 'ndvi',\n", + "}\n", + "\n", + "m.add_time_slider(collection, vis_params, time_interval=2)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a map for visualizing weather data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('NOAA/GFS0P25')\n", + " .filterDate('2018-12-22', '2018-12-23')\n", + " .limit(24)\n", + " .select('temperature_2m_above_ground')\n", + ")\n", + "\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "\n", + "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", + "m.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizing Sentinel-2 imagery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[37.75, -122.45], zoom=12)\n", + "\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", + " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", + ")\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "\n", + "m.add_time_slider(collection, vis_params)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "![](https://i.imgur.com/1b62CeI.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "m.center_object(centroid, 8)\n", + "m.add_layer(image, vis, \"Landsat-8\")\n", + "m.add_layer(centroid, {}, 'Centroid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = dataset.select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics with two images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dem = ee.Image('USGS/3DEP/10m')\n", + "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", + "m.add_layer(dem, vis, 'DEM')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "landcover = ee.Image(\"USGS/NLCD_RELEASES/2021_REL/NLCD/2021\").select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "m.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computer the mean elevation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", + "stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats.to_csv('mean.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the standard deviation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df('std.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coordinate grids and fishnets\n", + "\n", + "#### Creating coordinate grids\n", + "\n", + "Create a latitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lat_grid.style(**style), {}, 'Latitude Grid')\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(lat_grid)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a longitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(lon_grid.style(**style), {}, 'Longitude Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a rectangular grid with a 10-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = geemap.latlon_grid(\n", + " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(grid.style(**style), {}, 'Coordinate Grid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating fishnets\n", + "\n", + "Create a fishnet based on an Earth Engine geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with a 2-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a new map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Draw a polygon on the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.Polygon(\n", + " [\n", + " [\n", + " [-64.602356, -1.127399],\n", + " [-68.821106, -12.625598],\n", + " [-60.647278, -22.498601],\n", + " [-47.815247, -21.111406],\n", + " [-43.860168, -8.913564],\n", + " [-54.582825, -0.775886],\n", + " [-60.823059, 0.454555],\n", + " [-64.602356, -1.127399],\n", + " ]\n", + " ]\n", + " )\n", + " m.add_layer(roi, {}, 'ROI')\n", + "\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "m.add_layer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Land use and land cover change analysis\n", + "\n", + "#### Forest cover mapping\n", + "\n", + "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", + "dataset.bandNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", + "first_image = dataset.select(first_bands)\n", + "m.add_layer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Landsat 2000')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", + "last_image = dataset.select(last_bands)\n", + "m.add_layer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Landsat 2022')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the tree cover imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "treecover = dataset.select(['treecover2000'])\n", + "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", + "name = 'Tree cover (%)'\n", + "m.add_layer(treecover, treeCoverVisParam, name)\n", + "m.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract tree cover 2000 by using the threshold of 10%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "threshold = 10\n", + "treecover_bin = treecover.gte(threshold).selfMask()\n", + "treeVisParam = {'palette': ['green']}\n", + "m.add_layer(treecover_bin, treeVisParam, 'Tree cover bin')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Forest loss and gain mapping\n", + "\n", + "Visualize forest loss." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss_year = dataset.select(['lossyear'])\n", + "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", + "layer_name = 'Tree loss year'\n", + "m.add_layer(treeloss_year, treeLossVisParam, layer_name)\n", + "m.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare forest loss and gain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_basemap('Esri.WorldImagery')\n", + "treeloss = dataset.select(['loss']).selfMask()\n", + "treegain = dataset.select(['gain']).selfMask()\n", + "m.add_layer(treeloss, {'palette': 'red'}, 'Tree loss')\n", + "m.add_layer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", + "m.add('layer_manager')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by country\n", + "\n", + "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", + "\n", + "Add a country boundary layer to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", + "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", + "m.add_layer(countries.style(**style), {}, 'Countries')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treecover_bin,\n", + " countries,\n", + " 'forest_cover.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a pie chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart(\n", + " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'forest_cover.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treeloss.gt(0),\n", + " countries,\n", + " 'treeloss.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'treeloss.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest loss area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Analyzing forest cover gain and loss\n", + "\n", + "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", + "\n", + "![](https://i.imgur.com/NQ4UUnj.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 2 (10 mins)\n", + "\n", + "## Exporting Earth Engine data (30 mins)\n", + "\n", + "### Exporting images\n", + "\n", + "Add a Landsat image to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", + " ['B5', 'B4', 'B3']\n", + ")\n", + "\n", + "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "m.center_object(image)\n", + "m.add_layer(image, vis_params, 'Landsat')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a rectangle to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", + "fc = ee.FeatureCollection(region)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "m.add_layer(fc.style(**style), {}, 'ROI')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image projection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "projection = image.select(0).projection().getInfo()\n", + "projection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "crs = projection['crs']\n", + "crs_transform = projection['transform']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify region, crs, and crs_transform." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(\n", + " image,\n", + " filename=\"landsat_crs.tif\",\n", + " crs=crs,\n", + " crs_transform=crs_transform,\n", + " region=region,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_to_drive(\n", + " image, description='landsat', folder='export', region=region, scale=30\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "point = ee.Geometry.Point(-99.2222, 46.7816)\n", + "collection = (\n", + " ee.ImageCollection('USDA/NAIP/DOQQ')\n", + " .filterBounds(point)\n", + " .filterDate('2008-01-01', '2018-01-01')\n", + " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection.aggregate_array('system:index')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", + " ee.Filter.eq('country_na', 'Germany')\n", + ")\n", + "m.add_layer(fc, {}, \"Germany\")\n", + "m.center_object(fc)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector(fc, filename='Germany2.shp')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_geojson(fc, filename='Germany.geojson')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_csv(fc, filename='Germany.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdf = geemap.ee_to_gdf(fc)\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(fc)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector_to_drive(\n", + " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 5 - Exporting images by a fishnet\n", + "\n", + "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", + "\n", + "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", + "\n", + "![](https://i.imgur.com/L1IH3fq.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", + "m.add_layer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", + "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", + "m.add_layer(region, {}, 'ROI')\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", + "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " m.add_layer(roi, {}, 'ROI')\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", + "\n", + "![](https://i.imgur.com/ohrXeFC.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_gui(\"timelapse\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 3 (10 mins)\n", + "\n", + "## Building interactive web apps (30 mins)\n", + "\n", + "This section is optional. We might not have enough time to cover this section.\n", + "\n", + "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", + "\n", + "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", + "\n", + "After following the instructions above, you should have a web app that looks like this:\n", + "\n", + "![](https://i.imgur.com/X3ZFyRr.png)\n", + "\n", + "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/examples/workshops/GEE_Workshop_2021.ipynb b/examples/workshops/GEE_Workshop_2021.ipynb index 05f3ef9d0a..1c37b2b7d9 100644 --- a/examples/workshops/GEE_Workshop_2021.ipynb +++ b/examples/workshops/GEE_Workshop_2021.ipynb @@ -1065,7 +1065,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -1075,8 +1075,8 @@ "outputs": [], "source": [ "out_landsat_stats = os.path.join(out_dir, 'landsat_stats.csv')\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -1119,11 +1119,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -2766,4 +2766,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/GEE_Workshop_2022_Part2.ipynb b/examples/workshops/GEE_Workshop_2022_Part2.ipynb index ceda8374d5..277b3078af 100644 --- a/examples/workshops/GEE_Workshop_2022_Part2.ipynb +++ b/examples/workshops/GEE_Workshop_2022_Part2.ipynb @@ -620,7 +620,7 @@ " dataset,\n", " countries,\n", " 'esa_2021_country.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " scale=1000,\n", ")" @@ -865,7 +865,7 @@ " treecover_bin,\n", " countries,\n", " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " scale=1000,\n", ")" @@ -915,7 +915,7 @@ " treeloss,\n", " countries,\n", " 'treeloss.csv',\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " scale=1000,\n", ")" @@ -1158,4 +1158,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/GeoPython_2021.ipynb b/examples/workshops/GeoPython_2021.ipynb index 2e6c15374e..80494b0568 100644 --- a/examples/workshops/GeoPython_2021.ipynb +++ b/examples/workshops/GeoPython_2021.ipynb @@ -1028,7 +1028,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -1038,8 +1038,8 @@ "outputs": [], "source": [ "out_landsat_stats = os.path.join(out_dir, 'landsat_stats.csv')\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -1082,11 +1082,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -2737,4 +2737,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/Japan_2022.ipynb b/examples/workshops/Japan_2022.ipynb index bd8a12adcc..760efc2846 100644 --- a/examples/workshops/Japan_2022.ipynb +++ b/examples/workshops/Japan_2022.ipynb @@ -2025,7 +2025,7 @@ "source": [ "out_dem_stats = 'dem_stats.csv'\n", "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", ")" ] }, @@ -2040,7 +2040,7 @@ " landsat,\n", " states,\n", " out_landsat_stats,\n", - " statistics_type='MEAN',\n", + " stat_type='MEAN',\n", " scale=1000,\n", " return_fc=False,\n", ")" @@ -2088,7 +2088,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -2106,7 +2106,7 @@ " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", + " stat_type='PERCENTAGE',\n", " denominator=1e6,\n", " decimal_places=2,\n", ")" @@ -2978,4 +2978,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/NCSU_2023.ipynb b/examples/workshops/NCSU_2023.ipynb index 1d6da9b34e..b4c78f043a 100644 --- a/examples/workshops/NCSU_2023.ipynb +++ b/examples/workshops/NCSU_2023.ipynb @@ -1,1981 +1,1981 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", - "\n", - "**Interactive Cloud Computing with Google Earth Engine and geemap**\n", - "\n", - "- Notebook: \n", - "- Earth Engine: \n", - "- Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the workshop presented at the [GIS Week](https://www.gisweekatncstate.org/events-page) at North Carolina State University. \n", - "\n", - "### Abstract\n", - "\n", - "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", - "\n", - "### Prerequisites\n", - "\n", - "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", - "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", - "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", - "\n", - "### Change Colab dark theme\n", - "\n", - "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", - "\n", - "![](https://i.imgur.com/EJ0GDP8.png)\n", - "\n", - "\n", - "### Install geemap\n", - "\n", - "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install -U \"geemap[workshop]\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", - "\n", - "```bash\n", - "conda create -n gee python=3.11\n", - "conda activate gee\n", - "conda install -c conda-forge mamba\n", - "mamba install -c conda-forge geemap pygis\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries\n", - "\n", - "Import the earthengine-api and geemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(basemap='Esri.WorldImagery')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('Esri.WorldTopoMap')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also change basemaps interactively using the basemap GUI." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", - "}\n", - "m.add_layer(image, vis_params, 'SRTM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "m.set_center(83.277, 17.7009, 12)\n", - "m.add_layer(image, vis, 'Sentinel-2')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "m.set_center(-73.9596, 40.7688, 12)\n", - "m.add_layer(fc, {}, 'Census roads')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "m.add_layer(fc, {}, 'Louisiana')\n", - "m.center_object(fc, 7)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "m.add_layer(fc, {}, 'West Coast')\n", - "m.center_object(fc, 5)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = m.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "m.add_layer(fc, {}, 'Southeastern U.S.')\n", - "m.center_object(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "m.add_layer(states.style(**style), {}, \"US States\")\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "m.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "m.add_layer(dataset, {}, 'GAP CONUS')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery for a state of your choice for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/i3IT0lF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_layer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "m.add_layer(states, {}, \"US States\")\n", - "m.add('inspector')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", - "m.add_plot_gui()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Landsat." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set plotting options for Hyperion." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", - "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", - ")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(add_google_map=False)\n", - "\n", - "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m.add_basemap('Esri.WorldImagery')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", - "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "m.add_layer(dem, vis_params, 'SRTM DEM')\n", - "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Make the color bar background transparent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m.add_colorbar(\n", - " vis_params,\n", - " label=\"Elevation (m)\",\n", - " layer_name=\"SRTM DEM\",\n", - " orientation=\"vertical\",\n", - " max_width=\"100px\",\n", - " transparent_bg=True\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", - "\n", - "m.split_map(left_layer, right_layer)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "![](https://i.imgur.com/1b62CeI.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "m.center_object(centroid, 8)\n", - "m.add_layer(image, vis, \"Landsat-8\")\n", - "m.add_layer(centroid, {}, 'Centroid')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", - "landcover = dataset.select('landcover')\n", - "m.add_layer(landcover, {}, 'NLCD 2021')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "m.add_layer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", - "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "m.center_object(region)\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map(center=[40, -100], zoom=4)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " m.add_layer(roi, {}, 'ROI')\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "m.add_layer(roi)\n", - "m.center_object(roi)\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = m.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " m.add_layer(roi)\n", - " m.center_object(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", - "\n", - "![](https://i.imgur.com/ohrXeFC.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "m = geemap.Map()\n", - "m.add_gui(\"timelapse\")\n", - "m" - ] - } - ], - "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.11.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", + "\n", + "**Interactive Cloud Computing with Google Earth Engine and geemap**\n", + "\n", + "- Notebook: \n", + "- Earth Engine: \n", + "- Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the workshop presented at the [GIS Week](https://www.gisweekatncstate.org/events-page) at North Carolina State University. \n", + "\n", + "### Abstract\n", + "\n", + "This workshop provides an introduction to cloud-based geospatial analysis using the Earth Engine Python API. Attendees will learn the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment with geemap. Through practical examples and hands-on exercises, attendees will enhance their learning experience. During each hands-on session, attendees will walk through Jupyter Notebook examples on Google Colab. At the end of each session, they will complete a hands-on exercise to apply the knowledge they have learned.\n", + "\n", + "### Prerequisites\n", + "\n", + "- To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "- It is recommended that attendees have a basic understanding of Python and Jupyter Notebook.\n", + "- Familiarity with the Earth Engine JavaScript API is not required but will be helpful.\n", + "- Attendees can use Google Colab to follow this workshop without installing anything on their computer.\n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,900 GitHub stars and is being used by over 1,000 projects on GitHub.\n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/NCSU_2023.ipynb)\n", + "\n", + "### Change Colab dark theme\n", + "\n", + "Currently, ipywidgets does not work well with Colab dark theme. Some of the geemap widgets may not display properly in Colab dark theme.It is recommended that you change Colab to the light theme.\n", + "\n", + "![](https://i.imgur.com/EJ0GDP8.png)\n", + "\n", + "\n", + "### Install geemap\n", + "\n", + "The geemap package is pre-installed in Google Colab and is updated to the latest minor or major release every few weeks. Some optional dependencies of geemap being used by this notebook are not pre-installed in Colab. Uncomment the following line to install geemap and some optional dependencies." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install -U \"geemap[workshop]\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that some geemap features do not work properly with Google Colab. If you are familiar with [Anaconda](https://www.anaconda.com/distribution/#download-section) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html), it is recommended to create a new conda environment to install geemap and its optional dependencies on your local computer. \n", + "\n", + "```bash\n", + "conda create -n gee python=3.11\n", + "conda activate gee\n", + "conda install -c conda-forge mamba\n", + "mamba install -c conda-forge geemap pygis\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries\n", + "\n", + "Import the earthengine-api and geemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.m) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(basemap='Esri.WorldImagery')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('Esri.WorldTopoMap')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also change basemaps interactively using the basemap GUI." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'], # 'terrain'\n", + "}\n", + "m.add_layer(image, vis_params, 'SRTM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "m.set_center(83.277, 17.7009, 12)\n", + "m.add_layer(image, vis, 'Sentinel-2')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "m.set_center(-73.9596, 40.7688, 12)\n", + "m.add_layer(fc, {}, 'Census roads')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "m.add_layer(fc, {}, 'Louisiana')\n", + "m.center_object(fc, 7)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "m.add_layer(fc, {}, 'West Coast')\n", + "m.center_object(fc, 5)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = m.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "m.add_layer(fc, {}, 'Southeastern U.S.')\n", + "m.center_object(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "m.add_layer(states.style(**style), {}, \"US States\")\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "m.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of October 2023, the catalog contains over [1,000 datasets](https://github.com/opengeos/Earth-Engine-Catalog/blob/master/gee_catalog.tsv) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "m.add_layer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "m.add_layer(dataset, {}, 'GAP CONUS')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery for a state of your choice for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/i3IT0lF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_layer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "m.add_layer(states, {}, \"US States\")\n", + "m.add('inspector')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "m.add_layer(hyperion, hyperion_vis, 'Hyperion')\n", + "m.add_plot_gui()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Landsat." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set plotting options for Hyperion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.set_plot_options(add_marker_cluster=True, plot_type=\"bar\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "m.add_basemap('NLCD 2021 CONUS Land Cover')\n", + "m.add_legend(builtin_legend='NLCD', max_width='100px', height='455px')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='455px'\n", + ")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(add_google_map=False)\n", + "\n", + "keys = ['One', 'Two', 'Three', 'Four', 'etc']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "m.add_legend(keys=keys, colors=colors, position='bottomright')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m.add_basemap('Esri.WorldImagery')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "m.add_layer(landcover, {}, 'NLCD Land Cover 2021')\n", + "m.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "m.add_layer(dem, vis_params, 'SRTM DEM')\n", + "m.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make the color bar background transparent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m.add_colorbar(\n", + " vis_params,\n", + " label=\"Elevation (m)\",\n", + " layer_name=\"SRTM DEM\",\n", + " orientation=\"vertical\",\n", + " max_width=\"100px\",\n", + " transparent_bg=True\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps. Note that ipyleaflet has a bug with the SplitControl. You can't pan the map, which should be resolved in the next ipyleaflet release." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.split_map(left_layer='Esri.WorldTopoMap', right_layer='OpenTopoMap')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2021')\n", + "\n", + "m.split_map(left_layer, right_layer)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "![](https://i.imgur.com/1b62CeI.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "m.center_object(centroid, 8)\n", + "m.add_layer(image, vis, \"Landsat-8\")\n", + "m.add_layer(centroid, {}, 'Centroid')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "m.add_layer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "m.add_layer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2021_REL/NLCD/2021')\n", + "landcover = dataset.select('landcover')\n", + "m.add_layer(landcover, {}, 'NLCD 2021')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "m.add_layer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "m.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "m.add_layer(images, vis_params, \"Sentinel-2\", False)\n", + "m.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "m.center_object(region)\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map(center=[40, -100], zoom=4)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " m.add_layer(roi, {}, 'ROI')\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " m.add_layer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "m.add_layer(roi)\n", + "m.center_object(roi)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = m.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " m.add_layer(roi)\n", + " m.center_object(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/YaCHvKC.gif) example.\n", + "\n", + "![](https://i.imgur.com/ohrXeFC.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "m = geemap.Map()\n", + "m.add_gui(\"timelapse\")\n", + "m" + ] + } + ], + "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.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/examples/workshops/SRM_Workshop_2022.ipynb b/examples/workshops/SRM_Workshop_2022.ipynb index e2dbe722d8..37dfcd9173 100644 --- a/examples/workshops/SRM_Workshop_2022.ipynb +++ b/examples/workshops/SRM_Workshop_2022.ipynb @@ -1117,7 +1117,7 @@ "\n", "# Allowed output formats: csv, shp, json, kml, kmz\n", "# Allowed statistics type: MEAN, MAXIMUM, MINIMUM, MEDIAN, STD, MIN_MAX, VARIANCE, SUM\n", - "geemap.zonal_statistics(dem, states, out_dem_stats, statistics_type='MEAN', scale=1000)" + "geemap.zonal_stats(dem, states, out_dem_stats, stat_type='MEAN', scale=1000)" ] }, { @@ -1127,8 +1127,8 @@ "outputs": [], "source": [ "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_statistics(\n", - " landsat, states, out_landsat_stats, statistics_type='SUM', scale=1000\n", + "geemap.zonal_stats(\n", + " landsat, states, out_landsat_stats, stat_type='SUM', scale=1000\n", ")" ] }, @@ -1168,11 +1168,11 @@ "\n", "# statistics_type can be either 'SUM' or 'PERCENTAGE'\n", "# denominator can be used to convert square meters to other areal units, such as square kilimeters\n", - "geemap.zonal_statistics_by_group(\n", + "geemap.zonal_stats_by_group(\n", " landcover,\n", " states,\n", " nlcd_stats,\n", - " statistics_type='SUM',\n", + " stat_type='SUM',\n", " denominator=1000000,\n", " decimal_places=2,\n", ")" @@ -1607,4 +1607,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/examples/workshops/SciPy_2023.ipynb b/examples/workshops/SciPy_2023.ipynb index 4aa9087848..2939a7d794 100644 --- a/examples/workshops/SciPy_2023.ipynb +++ b/examples/workshops/SciPy_2023.ipynb @@ -1,3152 +1,3152 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", - "\n", - "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", - "\n", - "* Notebook: \n", - "* Earth Engine: \n", - "* Geemap: \n", - "\n", - "## Introduction (10 mins)\n", - "\n", - "This notebook is for the tutorial presented at the [SciPy 2023](https://www.scipy2023.org/) Conference by Qiusheng Wu and Steve Greenberg. Check out [this link](https://cfp.scipy.org/2023/talk/GQ7PG3/) for more information about the tutorial.\n", - "\n", - "### Abstract\n", - "\n", - "This tutorial is an introduction to cloud-based geospatial analysis with Earth Engine and the geemap Python package. We will cover the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment using geemap. We will also demonstrate how to develop and deploy interactive Earth Engine web apps. Throughout the session, practical examples and hands-on exercises will be provided to enhance learning. The attendees should have a basic understanding of Python and Jupyter Notebooks. Familiarity with Earth science and geospatial datasets is not required, but will be useful.\n", - "\n", - "\n", - "### Prerequisites\n", - "\n", - "To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", - "\n", - "### Prior Python Programming Level of Knowledge Expected\n", - "\n", - "The attendees are expected to have a basic understanding of Python and Jupyter Notebook. Familiarity with Earth science and geospatial datasets is not necessary, but it will be helpful.\n", - "\n", - "### G4G Summit Tickets\n", - "\n", - "We offer two [Geo for Good (G4G) Summit](https://earthoutreachonair.withgoogle.com/events/geoforgood23) tickets to attendees of the EE SciPy workshop. The G4G Summit will be held on October 11-12, 2023, at the Google campus in Mountain View, CA. The link to express your interest in the tickets will be provided during the workshop. \n", - "\n", - "## Introduction to Earth Engine and geemap (15 mins)\n", - "\n", - "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", - "\n", - "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", - "\n", - "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,700 GitHub stars and is being used by over 900 projects on GitHub. \n", - "\n", - "## Google Colab and Earth Engine Python API authentication (5 mins)\n", - "\n", - "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", - "\n", - "### Install geemap\n", - "\n", - "Uncomment the following line to install geemap if you are running this notebook in Google Colab." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %pip install geemap[workshop]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import libraries" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import ee\n", - "import geemap" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Authenticate and initialize Earth Engine\n", - "\n", - "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_initialize()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating interactive maps\n", - "\n", - "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.Map) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To display it in a Jupyter notebook, simply ask for the object representation:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4, height=600)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding basemaps\n", - "\n", - "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", - "\n", - "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(basemap='Esri.WorldImagery')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.add_basemap('OpenTopoMap')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Print out the first 10 basemaps:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps = list(geemap.basemaps.keys())\n", - "len(geemap.basemaps)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "basemaps[:10]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Earth Engine data (30 mins)\n", - "\n", - "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", - "\n", - "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", - "\n", - "- **Image**: the fundamental raster data type in Earth Engine.\n", - "- **ImageCollection**: a stack or time-series of images.\n", - "- **Geometry**: the fundamental vector data type in Earth Engine.\n", - "- **Feature**: a Geometry with attributes.\n", - "- **FeatureCollection**: a set of features.\n", - "\n", - "### Image\n", - "\n", - "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", - "\n", - "#### Loading Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = ee.Image('USGS/SRTMGL1_003')\n", - "image" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing Earth Engine images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[21.79, 70.87], zoom=3)\n", - "image = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 6000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "Map.addLayer(image, vis_params, 'SRTM')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ImageCollection\n", - "\n", - "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", - "\n", - "#### Loading image collections\n", - "\n", - "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection('COPERNICUS/S2_SR')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing image collections\n", - "\n", - "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "Map.setCenter(83.277, 17.7009, 12)\n", - "Map.addLayer(image, vis, 'Sentinel-2')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterDate('2021-01-01', '2022-01-01')\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", - ")\n", - "image = collection.median()\n", - "\n", - "vis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "Map.setCenter(83.277, 17.7009, 12)\n", - "Map.addLayer(image, vis, 'Sentinel-2')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### FeatureCollection\n", - "\n", - "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", - "\n", - "#### Loading feature collections\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", - "Map.setCenter(-73.9596, 40.7688, 12)\n", - "Map.addLayer(fc, {}, 'Census roads')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Filtering feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", - "Map.addLayer(fc, {}, 'Louisiana')\n", - "Map.centerObject(fc, 7)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feat = fc.first()\n", - "feat.toDictionary()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "states = ee.FeatureCollection('TIGER/2018/States')\n", - "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", - "Map.addLayer(fc, {}, 'West Coast')\n", - "Map.centerObject(fc, 5)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = Map.user_roi\n", - "if region is None:\n", - " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", - "\n", - "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", - "Map.addLayer(fc, {}, 'Southeastern U.S.')\n", - "Map.centerObject(fc, 6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Visualizing feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "Map.addLayer(states, {}, \"US States\")\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", - "Map.addLayer(states.style(**style), {}, \"US States\")\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "vis_params = {\n", - " 'color': '000000',\n", - " 'colorOpacity': 1,\n", - " 'pointSize': 3,\n", - " 'pointShape': 'circle',\n", - " 'width': 2,\n", - " 'lineType': 'solid',\n", - " 'fillColorOpacity': 0.66,\n", - "}\n", - "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", - "Map.add_styled_vector(\n", - " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", - ")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Earth Engine Data Catalog\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of March 2023, the catalog contains over [1,000 datasets](https://github.com/samapriya/Earth-Engine-Datasets-List) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", - "\n", - "#### Searching for datasets\n", - "\n", - "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", - "\n", - "![](https://i.imgur.com/B3rf4QN.jpg)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", - "Map.addLayer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Using the datasets module" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import DATA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", - "Map.addLayer(dataset, {}, 'GAP CONUS')\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.datasets import get_metadata\n", - "\n", - "get_metadata(DATA.USGS_GAP_CONUS_2011)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Converting Earth Engine JavaScripts to Python\n", - "\n", - "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Load an image.\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", - "\n", - "# Define the visualization parameters.\n", - "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "# Center the map and display the image.\n", - "Map.setCenter(-122.1899, 37.5010, 10)\n", - "# San Francisco Bay\n", - "Map.addLayer(image, vizParams, 'False color composite')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1 - Creating cloud-free imagery\n", - "\n", - "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", - "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", - "\n", - "![](https://i.imgur.com/DNIqGPY.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 1 (10 mins)\n", - "\n", - "## Visualizing Earth Engine data (30 mins)\n", - "\n", - "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", - "\n", - "### Using the inspector tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=(40, -100), zoom=4)\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", - "Map.addLayer(\n", - " landsat7,\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", - " 'Landsat 7',\n", - ")\n", - "Map.addLayer(states, {}, \"US States\")\n", - "Map.add_inspector()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the plotting tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", - " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", - ")\n", - "\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "Map.addLayer(landsat7, landsat_vis, \"Landsat\")\n", - "\n", - "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", - " ee.Filter.date('2016-01-01', '2017-03-01')\n", - ")\n", - "\n", - "hyperion_vis = {\n", - " 'min': 1000.0,\n", - " 'max': 14000.0,\n", - " 'gamma': 2.5,\n", - "}\n", - "Map.addLayer(hyperion, hyperion_vis, 'Hyperion')\n", - "Map.add_plot_gui()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.set_plot_options(add_marker_cluster=True, overlay=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Legends, color bars, and labels\n", - "\n", - "#### Built-in legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from geemap.legends import builtin_legends" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for legend in builtin_legends:\n", - " print(legend)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD WMS layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map.add_basemap('Google Hybrid')\n", - "Map.add_basemap('NLCD 2019 CONUS Land Cover')\n", - "Map.add_legend(builtin_legend='NLCD', max_width='100px')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add NLCD Earth Engine layer and legend to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map.add_basemap('HYBRID')\n", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", - "Map.add_legend(\n", - " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='460px'\n", - ")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Custom legends" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying the colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(add_google_map=False)\n", - "\n", - "labels = ['One', 'Two', 'Three', 'Four', 'ect']\n", - "\n", - "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", - "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", - "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", - "\n", - "Map.add_legend(labels=labels, colors=colors, position='bottomright')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a custom legend by specifying a dictionary of colors and labels." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map.add_basemap('Google Hybrid')\n", - "\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", - "\n", - "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", - "landcover = nlcd.select('landcover')\n", - "\n", - "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", - "Map.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating color bars\n", - "\n", - "Add a horizontal color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "vis_params = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "\n", - "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", - "Map.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a vertical color bar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.add_colorbar(\n", - " vis_params, \n", - " label=\"Elevation (m)\", \n", - " layer_name=\"SRTM DEM\", \n", - " orientation=\"vertical\",\n", - " max_width=\"100px\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Split-panel map and linked maps\n", - "\n", - "### Split-panel maps\n", - "\n", - "Create a split map with basemaps." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.split_map(left_layer='Google Terrain', right_layer='OpenTopoMap')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a split map with Earth Engine layers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=(40, -100), zoom=4, height=600)\n", - "\n", - "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", - "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019').select('landcover')\n", - "\n", - "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", - "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2019')\n", - "\n", - "Map.split_map(left_layer, right_layer)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Linked maps\n", - "\n", - "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image = (\n", - " ee.ImageCollection('COPERNICUS/S2')\n", - " .filterDate('2018-09-01', '2018-09-30')\n", - " .map(lambda img: img.divide(10000))\n", - " .median()\n", - ")\n", - "\n", - "vis_params = [\n", - " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", - "]\n", - "\n", - "labels = [\n", - " 'Natural Color (B4/B3/B2)',\n", - " 'Land/Water (B8/B11/B4)',\n", - " 'Color Infrared (B8/B4/B3)',\n", - " 'Vegetation (B12/B11/B4)',\n", - "]\n", - "\n", - "geemap.linked_maps(\n", - " rows=2,\n", - " cols=2,\n", - " height=\"300px\",\n", - " center=[38.4151, 21.2712],\n", - " zoom=12,\n", - " ee_objects=[image],\n", - " vis_params=vis_params,\n", - " labels=labels,\n", - " label_position=\"topright\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Timeseries inspector and time slider\n", - "\n", - "#### Timeseries inspector\n", - "\n", - "Check the available years of NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", - "vis_params = {'bands': ['landcover']}\n", - "years = collection.aggregate_array('system:index').getInfo()\n", - "years" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a timeseries inspector for NLCD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map.ts_inspector(\n", - " left_ts=collection,\n", - " right_ts=collection,\n", - " left_names=years,\n", - " right_names=years,\n", - " left_vis=vis_params,\n", - " right_vis=vis_params,\n", - " width='80px',\n", - ")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Time slider\n", - "\n", - "Create a map for visualizing MODIS vegetation data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", - " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", - " .select(\"NDVI\")\n", - ")\n", - "vis_params = {\n", - " 'min': 0.0,\n", - " 'max': 1.0,\n", - " 'palette': 'ndvi',\n", - "}\n", - "\n", - "Map.add_time_slider(collection, vis_params, time_interval=2)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a map for visualizing weather data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "collection = (\n", - " ee.ImageCollection('NOAA/GFS0P25')\n", - " .filterDate('2018-12-22', '2018-12-23')\n", - " .limit(24)\n", - " .select('temperature_2m_above_ground')\n", - ")\n", - "\n", - "vis_params = {\n", - " 'min': -40.0,\n", - " 'max': 35.0,\n", - " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", - "}\n", - "\n", - "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", - "Map.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualizing Sentinel-2 imagery" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[37.75, -122.45], zoom=12)\n", - "\n", - "collection = (\n", - " ee.ImageCollection('COPERNICUS/S2_SR')\n", - " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", - " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", - ")\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "\n", - "Map.add_time_slider(collection, vis_params)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2 - Creating land cover maps with a legend\n", - "\n", - "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", - "\n", - "\n", - "![](https://i.imgur.com/LJmztTd.png)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Analyzing Earth Engine data (30 mins)\n", - "\n", - "### Image descriptive statistics\n", - "\n", - "Use a sample Landsat image." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", - "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", - "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", - "\n", - "Map.centerObject(centroid, 8)\n", - "Map.addLayer(image, vis, \"Landsat-8\")\n", - "Map.addLayer(centroid, {}, 'Centroid')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.propertyNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image property values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.toDictionary()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get specific image properties." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "image.get('CLOUD_COVER') # 0.05" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get image properties with easy-to-read time format." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "props = geemap.image_props(image)\n", - "props" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute image descriptive statistics." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats(image, scale=30)\n", - "stats" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Zonal statistics\n", - "\n", - "#### Zonal statistics\n", - "\n", - "Add Earth Engine data to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NASA SRTM\n", - "dem = ee.Image('USGS/SRTMGL1_003')\n", - "dem_vis = {\n", - " 'min': 0,\n", - " 'max': 4000,\n", - " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", - "}\n", - "Map.addLayer(dem, dem_vis, 'SRTM DEM')\n", - "\n", - "# Add 5-year Landsat TOA composite\n", - "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", - "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", - "Map.addLayer(landsat, landsat_vis, \"Landsat\", False)\n", - "\n", - "# Add US Census States\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(states.style(**style), {}, 'US States')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_dem_stats = 'dem_stats.csv'\n", - "geemap.zonal_stats(\n", - " dem, states, out_dem_stats, statistics_type='MEAN', scale=1000, return_fc=False\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the csv file as a table." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics of mean spectral values of each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "out_landsat_stats = 'landsat_stats.csv'\n", - "geemap.zonal_stats(\n", - " landsat,\n", - " states,\n", - " out_landsat_stats,\n", - " statistics_type='MEAN',\n", - " scale=1000,\n", - " return_fc=False,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(out_landsat_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by group\n", - "\n", - "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "\n", - "# Add NLCD data\n", - "dataset = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", - "landcover = dataset.select('landcover')\n", - "Map.addLayer(landcover, {}, 'NLCD 2019')\n", - "\n", - "# Add US census states\n", - "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(states.style(**style), {}, 'US States')\n", - "\n", - "# Add NLCD legend\n", - "Map.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the percentage of each land cover type in each state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "nlcd_stats = 'nlcd_stats_pct.csv'\n", - "\n", - "geemap.zonal_stats_by_group(\n", - " landcover,\n", - " states,\n", - " nlcd_stats,\n", - " statistics_type='PERCENTAGE',\n", - " denominator=1e6,\n", - " decimal_places=2,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics with two images" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df(nlcd_stats)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by zone\n", - "\n", - "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "dem = ee.Image('USGS/3DEP/10m')\n", - "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", - "Map.addLayer(dem, vis, 'DEM')\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "landcover = ee.Image(\"USGS/NLCD_RELEASES/2019_REL/NLCD/2019\").select('landcover')\n", - "Map.addLayer(landcover, {}, 'NLCD 2019')\n", - "Map.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Computer the mean elevation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", - "stats" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stats.to_csv('mean.csv', index=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute the standard deviation of each land cover type." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.csv_to_df('std.csv')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Zonal statistics\n", - "\n", - "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", - "\n", - "![](https://i.imgur.com/GZCHHz3.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Coordinate grids and fishnets\n", - "\n", - "#### Creating coordinate grids\n", - "\n", - "Create a latitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(lat_grid.style(**style), {}, 'Latitude Grid')\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(lat_grid)\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a longitudinal grid with a 5-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(lon_grid.style(**style), {}, 'Longitude Grid')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a rectangular grid with a 10-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "grid = geemap.latlon_grid(\n", - " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "style = {'fillColor': '00000000'}\n", - "Map.addLayer(grid.style(**style), {}, 'Coordinate Grid')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Creating fishnets\n", - "\n", - "Create a fishnet based on an Earth Engine geometry." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", - " Map.addLayer(roi, {}, 'ROI')\n", - " Map.user_roi = None\n", - "\n", - "Map.centerObject(roi)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with a 2-degree interval." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a new map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Draw a polygon on the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "\n", - "if roi is None:\n", - " roi = ee.Geometry.Polygon(\n", - " [\n", - " [\n", - " [-64.602356, -1.127399],\n", - " [-68.821106, -12.625598],\n", - " [-60.647278, -22.498601],\n", - " [-47.815247, -21.111406],\n", - " [-43.860168, -8.913564],\n", - " [-54.582825, -0.775886],\n", - " [-60.823059, 0.454555],\n", - " [-64.602356, -1.127399],\n", - " ]\n", - " ]\n", - " )\n", - " Map.addLayer(roi, {}, 'ROI')\n", - "\n", - "Map.centerObject(roi)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", - "style = {'color': 'blue', 'fillColor': '00000000'}\n", - "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Land use and land cover change analysis\n", - "\n", - "#### Forest cover mapping\n", - "\n", - "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", - "dataset.bandNames()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", - "first_image = dataset.select(first_bands)\n", - "Map.addLayer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Year 2000 Bands 5/4/3')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the imagery for 2022." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", - "last_image = dataset.select(last_bands)\n", - "Map.addLayer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Year 2022 Bands 5/4/3')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Select the tree cover imagery for 2000." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "treecover = dataset.select(['treecover2000'])\n", - "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", - "name = 'Tree cover (%)'\n", - "Map.addLayer(treecover, treeCoverVisParam, name)\n", - "Map.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extract tree cover 2000 by using the threshold of 10%." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "threshold = 10\n", - "treecover_bin = treecover.gte(threshold).selfMask()\n", - "treeVisParam = {'palette': ['green']}\n", - "Map.addLayer(treecover_bin, treeVisParam, 'Tree cover bin')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Forest loss and gain mapping\n", - "\n", - "Visualize forest loss." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.add_basemap('Google Hybrid')\n", - "treeloss_year = dataset.select(['lossyear'])\n", - "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", - "layer_name = 'Tree loss year since 2000'\n", - "Map.addLayer(treeloss_year, treeLossVisParam, layer_name)\n", - "Map.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compare forest loss and gain." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.add_basemap('Google Hybrid')\n", - "treeloss = dataset.select(['loss']).selfMask()\n", - "treegain = dataset.select(['gain']).selfMask()\n", - "Map.addLayer(treeloss, {'palette': 'red'}, 'Tree loss')\n", - "Map.addLayer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", - "Map.add_layer_manager()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Zonal statistics by country\n", - "\n", - "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", - "\n", - "Add a country boundary layer to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", - "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", - "Map.addLayer(countries.style(**style), {}, 'Countries')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Compute zonal statistics by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treecover_bin,\n", - " countries,\n", - " 'forest_cover.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pie chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart(\n", - " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'forest_cover.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Calculate the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.zonal_stats(\n", - " treeloss.gt(0),\n", - " countries,\n", - " 'treeloss.csv',\n", - " statistics_type='SUM',\n", - " denominator=1e6,\n", - " scale=1000,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a bar chart to visualize the forest loss area by country." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.bar_chart(\n", - " 'treeloss.csv',\n", - " x='NAME',\n", - " y='sum',\n", - " max_rows=20,\n", - " x_label='Country',\n", - " y_label='Forest loss area (km2)',\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4 - Analyzing forest cover gain and loss\n", - "\n", - "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", - "\n", - "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", - "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", - "\n", - "![](https://i.imgur.com/t5sH5ku.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break 2 (10 mins)\n", - "\n", - "## Exporting Earth Engine data (30 mins)\n", - "\n", - "### Exporting images\n", - "\n", - "Add a Landsat image to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", - " ['B5', 'B4', 'B3']\n", - ")\n", - "\n", - "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", - "\n", - "Map.centerObject(image)\n", - "Map.addLayer(image, vis_params, 'Landsat')\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add a rectangle to the map." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", - "fc = ee.FeatureCollection(region)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "Map.addLayer(fc.style(**style), {}, 'ROI')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check image projection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "projection = image.select(0).projection().getInfo()\n", - "projection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "crs = projection['crs']\n", - "crs_transform = projection['transform']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify region, crs, and crs_transform." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image(\n", - " image,\n", - " filename=\"landsat_crs.tif\",\n", - " crs=crs,\n", - " crs_transform=crs_transform,\n", - " region=region,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_to_drive(\n", - " image, description='landsat', folder='export', region=region, scale=30\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting image collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "point = ee.Geometry.Point(-99.2222, 46.7816)\n", - "collection = (\n", - " ee.ImageCollection('USDA/NAIP/DOQQ')\n", - " .filterBounds(point)\n", - " .filterDate('2008-01-01', '2018-01-01')\n", - " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection.aggregate_array('system:index')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exporting feature collections" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", - " ee.Filter.eq('country_na', 'Germany')\n", - ")\n", - "Map.addLayer(fc, {}, \"Germany\")\n", - "Map.centerObject(fc)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To local drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector(fc, filename='Germany2.shp')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_geojson(fc, filename='Germany.geojson')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_to_csv(fc, filename='Germany.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gdf = geemap.ee_to_gdf(fc)\n", - "gdf" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "df = geemap.ee_to_df(fc)\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To Google Drive" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.ee_export_vector_to_drive(\n", - " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5 - Exporting images by a fishnet\n", - "\n", - "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", - "\n", - "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", - "\n", - "![](https://i.imgur.com/L1IH3fq.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", - "Map.addLayer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", - "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", - "Map.addLayer(region, {}, 'ROI')\n", - "Map.centerObject(region)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "fishnet = geemap.fishnet(region, h_interval=4.0, v_interval=4.0, delta=0.5)\n", - "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", - "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.download_ee_image_tiles(\n", - " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "geemap.download_ee_image_tiles_parallel(\n", - " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "## Creating Satellite timelapse animations (30 mins)\n", - "\n", - "### Creating satellite timeseries\n", - "\n", - "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", - " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Specify the location of interest and date range." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "start_date = '2016-01-01'\n", - "end_date = '2022-12-31'\n", - "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create an annual composite." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "images = geemap.create_timeseries(\n", - " collection, start_date, end_date, region, frequency='year', reducer='median'\n", - ")\n", - "images" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Display the timeseries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "\n", - "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", - "labels = [str(y) for y in range(2016, 2023)]\n", - "\n", - "Map.addLayer(images, vis_params, \"Sentinel-2\", False)\n", - "Map.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", - "Map.centerObject(region)\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Creating satellite timelapse animations\n", - "\n", - "#### NAIP timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map(center=[40, -100], zoom=4)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", - " Map.addLayer(roi, {}, 'ROI')\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", - "print(years)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "size = len(years)\n", - "images = collection.toList(size)\n", - "for i in range(size):\n", - " image = ee.Image(images.get(i))\n", - " Map.addLayer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.naip_timelapse(\n", - " roi,\n", - " out_gif=\"naip.gif\",\n", - " bands=['N', 'R', 'G'],\n", - " frames_per_second=3,\n", - " title='NAIP Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Landsat timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='landsat.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=5,\n", - " title='Landsat Timelapse',\n", - " progress_bar_color='blue',\n", - " mp4=True,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", - "Map.addLayer(roi)\n", - "Map.centerObject(roi)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='las_vegas.gif',\n", - " start_year=1984,\n", - " end_year=2022,\n", - " bands=['NIR', 'Red', 'Green'],\n", - " frames_per_second=5,\n", - " title='Las Vegas, NV',\n", - " font_color='blue',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", - "Map.addLayer(roi)\n", - "Map.centerObject(roi)\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.landsat_timelapse(\n", - " roi,\n", - " out_gif='hong_kong.gif',\n", - " start_year=1990,\n", - " end_year=2022,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Hong Kong',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sentinel-2 timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.sentinel2_timelapse(\n", - " roi,\n", - " out_gif='sentinel2.gif',\n", - " start_year=2016,\n", - " end_year=2021,\n", - " start_date='01-01',\n", - " end_date='12-31',\n", - " frequency='year',\n", - " bands=['SWIR1', 'NIR', 'Red'],\n", - " frames_per_second=3,\n", - " title='Sentinel-2 Timelapse',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### MODIS timelapse\n", - "\n", - "MODIS vegetation indices" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ndvi_timelapse(\n", - " roi,\n", - " out_gif='ndvi.gif',\n", - " data='Terra',\n", - " band='NDVI',\n", - " start_date='2000-01-01',\n", - " end_date='2022-12-31',\n", - " frames_per_second=3,\n", - " title='MODIS NDVI Timelapse',\n", - " overlay_data='countries',\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MODIS temperature" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = Map.user_roi\n", - "if roi is None:\n", - " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", - " Map.addLayer(roi)\n", - " Map.centerObject(roi)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.modis_ocean_color_timelapse(\n", - " satellite='Aqua',\n", - " start_date='2018-01-01',\n", - " end_date='2020-12-31',\n", - " roi=roi,\n", - " frequency='month',\n", - " out_gif='temperature.gif',\n", - " overlay_data='continents',\n", - " overlay_color='yellow',\n", - " overlay_opacity=0.5,\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### GOES timelapse" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", - "start_date = \"2022-01-15T03:00:00\"\n", - "end_date = \"2022-01-15T07:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", - "start_date = \"2021-10-24T14:00:00\"\n", - "end_date = \"2021-10-25T01:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_timelapse(\n", - " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", - "start_date = \"2020-09-05T15:00:00\"\n", - "end_date = \"2020-09-06T02:00:00\"\n", - "data = \"GOES-17\"\n", - "scan = \"full_disk\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "timelapse = geemap.goes_fire_timelapse(\n", - " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", - ")\n", - "geemap.show_image(timelapse)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Creating timelapse animations\n", - "\n", - "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/uFaXD9s.gif) example.\n", - "\n", - "![](https://i.imgur.com/vecPydF.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Map = geemap.Map()\n", - "Map.add_gui(\"timelapse\")\n", - "Map" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "\n", - "## Break 3 (10 mins)\n", - "\n", - "## Building interactive web apps (30 mins)\n", - "\n", - "This section is optional. We might not have enough time to cover this section.\n", - "\n", - "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", - "\n", - "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", - "\n", - "After following the instructions above, you should have a web app that looks like this:\n", - "\n", - "![](https://i.imgur.com/uYDUPl0.png)\n", - "\n", - "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.10.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", + "\n", + "**An Introduction to Cloud-Based Geospatial Analysis with Earth Engine and Geemap**\n", + "\n", + "* Notebook: \n", + "* Earth Engine: \n", + "* Geemap: \n", + "\n", + "## Introduction (10 mins)\n", + "\n", + "This notebook is for the tutorial presented at the [SciPy 2023](https://www.scipy2023.org/) Conference by Qiusheng Wu and Steve Greenberg. Check out [this link](https://cfp.scipy.org/2023/talk/GQ7PG3/) for more information about the tutorial.\n", + "\n", + "### Abstract\n", + "\n", + "This tutorial is an introduction to cloud-based geospatial analysis with Earth Engine and the geemap Python package. We will cover the basics of Earth Engine data types and how to visualize, analyze, and export Earth Engine data in a Jupyter environment using geemap. We will also demonstrate how to develop and deploy interactive Earth Engine web apps. Throughout the session, practical examples and hands-on exercises will be provided to enhance learning. The attendees should have a basic understanding of Python and Jupyter Notebooks. Familiarity with Earth science and geospatial datasets is not required, but will be useful.\n", + "\n", + "\n", + "### Prerequisites\n", + "\n", + "To use geemap and the Earth Engine Python API, you must [register](https://code.earthengine.google.com/register) for an Earth Engine account and follow the instructions [here](https://docs.google.com/document/d/1ZGSmrNm6_baqd8CHt33kIBWOlvkh-HLr46bODgJN1h0/edit?usp=sharing) to create a Cloud Project. Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). To test whether you can use authenticate the Earth Engine Python API, please run [this notebook](https://colab.research.google.com/github/giswqs/geemap/blob/master/examples/notebooks/geemap_colab.ipynb) on Google Colab.\n", + "\n", + "### Prior Python Programming Level of Knowledge Expected\n", + "\n", + "The attendees are expected to have a basic understanding of Python and Jupyter Notebook. Familiarity with Earth science and geospatial datasets is not necessary, but it will be helpful.\n", + "\n", + "### G4G Summit Tickets\n", + "\n", + "We offer two [Geo for Good (G4G) Summit](https://earthoutreachonair.withgoogle.com/events/geoforgood23) tickets to attendees of the EE SciPy workshop. The G4G Summit will be held on October 11-12, 2023, at the Google campus in Mountain View, CA. The link to express your interest in the tickets will be provided during the workshop. \n", + "\n", + "## Introduction to Earth Engine and geemap (15 mins)\n", + "\n", + "Earth Engine is free for [noncommercial and research use](https://earthengine.google.com/noncommercial). For more than a decade, Earth Engine has enabled planetary-scale Earth data science and analysis by nonprofit organizations, research scientists, and other impact users.\n", + "\n", + "With the launch of Earth Engine for [commercial use](https://earthengine.google.com/commercial), commercial customers will be charged for Earth Engine services. However, Earth Engine will remain free of charge for noncommercial use and research projects. Nonprofit organizations, academic institutions, educators, news media, Indigenous governments, and government researchers are eligible to use Earth Engine free of charge, just as they have done for over a decade.\n", + "\n", + "The geemap Python package is built upon the Earth Engine Python API and open-source mapping libraries. It allows Earth Engine users to interactively manipulate, analyze, and visualize geospatial big data in a Jupyter environment. Since its creation in April 2020, geemap has received over 2,700 GitHub stars and is being used by over 900 projects on GitHub. \n", + "\n", + "## Google Colab and Earth Engine Python API authentication (5 mins)\n", + "\n", + "[![image](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/gee-community/geemap/blob/master/docs/workshops/SciPy_2023.ipynb)\n", + "\n", + "### Install geemap\n", + "\n", + "Uncomment the following line to install geemap if you are running this notebook in Google Colab." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# %pip install geemap[workshop]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import libraries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import ee\n", + "import geemap" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Authenticate and initialize Earth Engine\n", + "\n", + "You will need to create a [Google Cloud Project](https://console.cloud.google.com/projectcreate) and enable the [Earth Engine API](https://console.cloud.google.com/apis/api/earthengine.googleapis.com) for the project. You can find detailed instructions [here](https://book.geemap.org/chapters/01_introduction.html#earth-engine-authentication)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_initialize()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating interactive maps\n", + "\n", + "Let's create an interactive map using the `ipyleaflet` plotting backend. The [`geemap.Map`](https://geemap.org/geemap/#geemap.geemap.Map) class inherits the [`ipyleaflet.Map`](https://ipyleaflet.readthedocs.io/en/latest/map_and_basemaps/map.html) class. Therefore, you can use the same syntax to create an interactive map as you would with `ipyleaflet.Map`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display it in a Jupyter notebook, simply ask for the object representation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To customize the map, you can specify various keyword arguments, such as `center` ([lat, lon]), `zoom`, `width`, and `height`. The default `width` is `100%`, which takes up the entire cell width of the Jupyter notebook. The `height` argument accepts a number or a string. If a number is provided, it represents the height of the map in pixels. If a string is provided, the string must be in the format of a number followed by `px`, e.g., `600px`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4, height=600)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To hide a control, set `control_name` to `False`, e.g., `draw_ctrl=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(data_ctrl=False, toolbar_ctrl=False, draw_ctrl=False)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding basemaps\n", + "\n", + "There are several ways to add basemaps to a map. You can specify the basemap to use in the `basemap` keyword argument when creating the map. Alternatively, you can add basemap layers to the map using the `add_basemap` method. Geemap has hundreds of built-in basemaps available that can be easily added to the map with only one line of code.\n", + "\n", + "Create a map by specifying the basemap to use as follows. For example, the `Esri.WorldImagery` basemap represents the Esri world imagery basemap." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(basemap='Esri.WorldImagery')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can add as many basemaps as you like to the map. For example, the following code adds the `OpenTopoMap` basemap to the map above:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.add_basemap('OpenTopoMap')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print out the first 10 basemaps:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps = list(geemap.basemaps.keys())\n", + "len(geemap.basemaps)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "basemaps[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Earth Engine data (30 mins)\n", + "\n", + "### Earth Engine data types (Image, ImageCollection, Geometry, Feature, FeatureCollection)\n", + "\n", + "Earth Engine objects are server-side objects rather than client-side objects, which means that they are not stored locally on your computer. Similar to video streaming services (e.g., YouTube, Netflix, and Hulu), which store videos/movies on their servers, Earth Engine data are stored on the Earth Engine servers. We can stream geospatial data from Earth Engine on-the-fly without having to download the data just like we can watch videos from streaming services using a web browser without having to download the entire video to your computer.\n", + "\n", + "- **Image**: the fundamental raster data type in Earth Engine.\n", + "- **ImageCollection**: a stack or time-series of images.\n", + "- **Geometry**: the fundamental vector data type in Earth Engine.\n", + "- **Feature**: a Geometry with attributes.\n", + "- **FeatureCollection**: a set of features.\n", + "\n", + "### Image\n", + "\n", + "Raster data in Earth Engine are represented as **Image** objects. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties.\n", + "\n", + "#### Loading Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = ee.Image('USGS/SRTMGL1_003')\n", + "image" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing Earth Engine images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[21.79, 70.87], zoom=3)\n", + "image = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 6000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "Map.addLayer(image, vis_params, 'SRTM')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ImageCollection\n", + "\n", + "An `ImageCollection` is a stack or sequence of images. An `ImageCollection` can be loaded by passing an Earth Engine asset ID into the `ImageCollection` constructor. You can find `ImageCollection` IDs in the [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets).\n", + "\n", + "#### Loading image collections\n", + "\n", + "For example, to load the image collection of the [Sentinel-2 surface reflectance](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection('COPERNICUS/S2_SR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing image collections\n", + "\n", + "To visualize an Earth Engine **ImageCollection**, we need to convert an **ImageCollection** to an **Image** by compositing all the images in the collection to a single image representing, for example, the min, max, median, mean or standard deviation of the images. For example, to create a median value image from a collection, use the `collection.median()` method. Let's create a median image from the Sentinel-2 surface reflectance collection:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "collection = ee.ImageCollection('COPERNICUS/S2_SR')\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "Map.setCenter(83.277, 17.7009, 12)\n", + "Map.addLayer(image, vis, 'Sentinel-2')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterDate('2021-01-01', '2022-01-01')\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 5))\n", + ")\n", + "image = collection.median()\n", + "\n", + "vis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "Map.setCenter(83.277, 17.7009, 12)\n", + "Map.addLayer(image, vis, 'Sentinel-2')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FeatureCollection\n", + "\n", + "A **FeatureCollection** is a collection of Features. A FeatureCollection is analogous to a GeoJSON FeatureCollection object, i.e., a collection of features with associated properties/attributes. Data contained in a shapefile can be represented as a FeatureCollection.\n", + "\n", + "#### Loading feature collections\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of vector datasets (e.g,, US Census data, country boundaries, and more) as feature collections. You can find feature collection IDs by searching the data catalog. For example, to load the [TIGER roads data](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2016_Roads) by the U.S. Census Bureau:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "fc = ee.FeatureCollection('TIGER/2016/Roads')\n", + "Map.setCenter(-73.9596, 40.7688, 12)\n", + "Map.addLayer(fc, {}, 'Census roads')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Filtering feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.eq('NAME', 'Louisiana'))\n", + "Map.addLayer(fc, {}, 'Louisiana')\n", + "Map.centerObject(fc, 7)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feat = fc.first()\n", + "feat.toDictionary()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "states = ee.FeatureCollection('TIGER/2018/States')\n", + "fc = states.filter(ee.Filter.inList('NAME', ['California', 'Oregon', 'Washington']))\n", + "Map.addLayer(fc, {}, 'West Coast')\n", + "Map.centerObject(fc, 5)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = Map.user_roi\n", + "if region is None:\n", + " region = ee.Geometry.BBox(-88.40, 29.88, -77.90, 35.39)\n", + "\n", + "fc = ee.FeatureCollection('TIGER/2018/States').filterBounds(region)\n", + "Map.addLayer(fc, {}, 'Southeastern U.S.')\n", + "Map.centerObject(fc, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Visualizing feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "Map.addLayer(states, {}, \"US States\")\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'color': '0000ffff', 'width': 2, 'lineType': 'solid', 'fillColor': 'FF000080'}\n", + "Map.addLayer(states.style(**style), {}, \"US States\")\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "vis_params = {\n", + " 'color': '000000',\n", + " 'colorOpacity': 1,\n", + " 'pointSize': 3,\n", + " 'pointShape': 'circle',\n", + " 'width': 2,\n", + " 'lineType': 'solid',\n", + " 'fillColorOpacity': 0.66,\n", + "}\n", + "palette = ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", + "Map.add_styled_vector(\n", + " states, column=\"NAME\", palette=palette, layer_name=\"Styled vector\", **vis_params\n", + ")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Earth Engine Data Catalog\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets) hosts a variety of geospatial datasets. As of March 2023, the catalog contains over [1,000 datasets](https://github.com/samapriya/Earth-Engine-Datasets-List) with a total size of over 80 petabytes. Some notable datasets include: Landsat, Sentinel, MODIS, NAIP, etc. For a complete list of datasets in CSV or JSON formats, see the [Earth Engine Datasets List](https://github.com/giswqs/Earth-Engine-Catalog/blob/master/gee_catalog.tsv).\n", + "\n", + "#### Searching for datasets\n", + "\n", + "The [Earth Engine Data Catalog](https://developers.google.com/earth-engine/datasets/catalog) is searchable. You can search datasets by name, keyword, or tag. For example, enter \"elevation\" in the search box will filter the catalog to show only datasets containing \"elevation\" in their name, description, or tags. 52 datasets are returned for this search query. Scroll down the list to find the [NASA SRTM Digital Elevation 30m](https://developers.google.com/earth-engine/datasets/catalog/USGS_SRTMGL1_003#description) dataset. On each dataset page, you can find the following information, including Dataset Availability, Dataset Provider, Earth Engine Snippet, Tags, Description, Code Example, and more (see {numref}`ch03_gee_srtm`). One important piece of information is the Image/ImageCollection/FeatureCollection ID of each dataset, which is essential for accessing the dataset through the Earth Engine JavaScript or Python APIs.\n", + "\n", + "![](https://i.imgur.com/B3rf4QN.jpg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset_xyz = ee.Image('USGS/SRTMGL1_003')\n", + "Map.addLayer(dataset_xyz, {}, \"USGS/SRTMGL1_003\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Using the datasets module" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import DATA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "dataset = ee.Image(DATA.USGS_GAP_CONUS_2011)\n", + "Map.addLayer(dataset, {}, 'GAP CONUS')\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.datasets import get_metadata\n", + "\n", + "get_metadata(DATA.USGS_GAP_CONUS_2011)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Converting Earth Engine JavaScripts to Python\n", + "\n", + "Find some Earth Engine JavaScript code that you want to convert to Python. For example, you can grab some sample code from the [Earth Engine Documentation](https://developers.google.com/earth-engine/guides/image_visualization)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Load an image.\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318')\n", + "\n", + "# Define the visualization parameters.\n", + "vizParams = {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "# Center the map and display the image.\n", + "Map.setCenter(-122.1899, 37.5010, 10)\n", + "# San Francisco Bay\n", + "Map.addLayer(image, vizParams, 'False color composite')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 1 - Creating cloud-free imagery\n", + "\n", + "Create a cloud-free imagery of Texas for the year of 2022. You can use either Landsat 9 or Sentinel-2 imagery. Relevant Earth Engine assets:\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"COPERNICUS/S2_SR\")](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR)\n", + "- [ee.ImageCollection(\"LANDSAT/LC09/C02/T1_L2\")](https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2)\n", + "\n", + "![](https://i.imgur.com/DNIqGPY.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 1 (10 mins)\n", + "\n", + "## Visualizing Earth Engine data (30 mins)\n", + "\n", + "### Geemap Inspector tool, plotting tool, interactive GUI for data visualization\n", + "\n", + "### Using the inspector tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=(40, -100), zoom=4)\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", + "Map.addLayer(\n", + " landsat7,\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 20, 'max': 200, 'gamma': 2.0},\n", + " 'Landsat 7',\n", + ")\n", + "Map.addLayer(states, {}, \"US States\")\n", + "Map.add_inspector()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using the plotting tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "landsat7 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(\n", + " ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']\n", + ")\n", + "\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "Map.addLayer(landsat7, landsat_vis, \"Landsat\")\n", + "\n", + "hyperion = ee.ImageCollection('EO1/HYPERION').filter(\n", + " ee.Filter.date('2016-01-01', '2017-03-01')\n", + ")\n", + "\n", + "hyperion_vis = {\n", + " 'min': 1000.0,\n", + " 'max': 14000.0,\n", + " 'gamma': 2.5,\n", + "}\n", + "Map.addLayer(hyperion, hyperion_vis, 'Hyperion')\n", + "Map.add_plot_gui()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.set_plot_options(add_marker_cluster=True, overlay=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Legends, color bars, and labels\n", + "\n", + "#### Built-in legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from geemap.legends import builtin_legends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for legend in builtin_legends:\n", + " print(legend)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD WMS layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map.add_basemap('Google Hybrid')\n", + "Map.add_basemap('NLCD 2019 CONUS Land Cover')\n", + "Map.add_legend(builtin_legend='NLCD', max_width='100px')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add NLCD Earth Engine layer and legend to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map.add_basemap('HYBRID')\n", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", + "Map.add_legend(\n", + " title=\"NLCD Land Cover Classification\", builtin_legend='NLCD', height='460px'\n", + ")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Custom legends" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying the colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(add_google_map=False)\n", + "\n", + "labels = ['One', 'Two', 'Three', 'Four', 'ect']\n", + "\n", + "# colors can be defined using either hex code or RGB (0-255, 0-255, 0-255)\n", + "colors = ['#8DD3C7', '#FFFFB3', '#BEBADA', '#FB8072', '#80B1D3']\n", + "# legend_colors = [(255, 0, 0), (127, 255, 0), (127, 18, 25), (36, 70, 180), (96, 68 123)]\n", + "\n", + "Map.add_legend(labels=labels, colors=colors, position='bottomright')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a custom legend by specifying a dictionary of colors and labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map.add_basemap('Google Hybrid')\n", + "\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", + "\n", + "nlcd = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", + "landcover = nlcd.select('landcover')\n", + "\n", + "Map.addLayer(landcover, {}, 'NLCD Land Cover 2019')\n", + "Map.add_legend(title=\"NLCD Land Cover Classification\", legend_dict=legend_dict)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating color bars\n", + "\n", + "Add a horizontal color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "vis_params = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "\n", + "Map.addLayer(dem, vis_params, 'SRTM DEM')\n", + "Map.add_colorbar(vis_params, label=\"Elevation (m)\", layer_name=\"SRTM DEM\")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a vertical color bar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.add_colorbar(\n", + " vis_params, \n", + " label=\"Elevation (m)\", \n", + " layer_name=\"SRTM DEM\", \n", + " orientation=\"vertical\",\n", + " max_width=\"100px\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Split-panel map and linked maps\n", + "\n", + "### Split-panel maps\n", + "\n", + "Create a split map with basemaps." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.split_map(left_layer='Google Terrain', right_layer='OpenTopoMap')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a split map with Earth Engine layers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=(40, -100), zoom=4, height=600)\n", + "\n", + "nlcd_2001 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2001').select('landcover')\n", + "nlcd_2019 = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019').select('landcover')\n", + "\n", + "left_layer = geemap.ee_tile_layer(nlcd_2001, {}, 'NLCD 2001')\n", + "right_layer = geemap.ee_tile_layer(nlcd_2019, {}, 'NLCD 2019')\n", + "\n", + "Map.split_map(left_layer, right_layer)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linked maps\n", + "\n", + "Create a 2x2 linked map for visualizing Sentinel-2 imagery with different band combinations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = (\n", + " ee.ImageCollection('COPERNICUS/S2')\n", + " .filterDate('2018-09-01', '2018-09-30')\n", + " .map(lambda img: img.divide(10000))\n", + " .median()\n", + ")\n", + "\n", + "vis_params = [\n", + " {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B11', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B8', 'B4', 'B3'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + " {'bands': ['B12', 'B12', 'B4'], 'min': 0, 'max': 0.3, 'gamma': 1.3},\n", + "]\n", + "\n", + "labels = [\n", + " 'Natural Color (B4/B3/B2)',\n", + " 'Land/Water (B8/B11/B4)',\n", + " 'Color Infrared (B8/B4/B3)',\n", + " 'Vegetation (B12/B11/B4)',\n", + "]\n", + "\n", + "geemap.linked_maps(\n", + " rows=2,\n", + " cols=2,\n", + " height=\"300px\",\n", + " center=[38.4151, 21.2712],\n", + " zoom=12,\n", + " ee_objects=[image],\n", + " vis_params=vis_params,\n", + " labels=labels,\n", + " label_position=\"topright\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Timeseries inspector and time slider\n", + "\n", + "#### Timeseries inspector\n", + "\n", + "Check the available years of NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "collection = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD').select('landcover')\n", + "vis_params = {'bands': ['landcover']}\n", + "years = collection.aggregate_array('system:index').getInfo()\n", + "years" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a timeseries inspector for NLCD." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map.ts_inspector(\n", + " left_ts=collection,\n", + " right_ts=collection,\n", + " left_names=years,\n", + " right_names=years,\n", + " left_vis=vis_params,\n", + " right_vis=vis_params,\n", + " width='80px',\n", + ")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Time slider\n", + "\n", + "Create a map for visualizing MODIS vegetation data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('MODIS/MCD43A4_006_NDVI')\n", + " .filter(ee.Filter.date('2018-06-01', '2018-07-01'))\n", + " .select(\"NDVI\")\n", + ")\n", + "vis_params = {\n", + " 'min': 0.0,\n", + " 'max': 1.0,\n", + " 'palette': 'ndvi',\n", + "}\n", + "\n", + "Map.add_time_slider(collection, vis_params, time_interval=2)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a map for visualizing weather data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "collection = (\n", + " ee.ImageCollection('NOAA/GFS0P25')\n", + " .filterDate('2018-12-22', '2018-12-23')\n", + " .limit(24)\n", + " .select('temperature_2m_above_ground')\n", + ")\n", + "\n", + "vis_params = {\n", + " 'min': -40.0,\n", + " 'max': 35.0,\n", + " 'palette': ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'],\n", + "}\n", + "\n", + "labels = [str(n).zfill(2) + \":00\" for n in range(0, 24)]\n", + "Map.add_time_slider(collection, vis_params, labels=labels, time_interval=1, opacity=0.8)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualizing Sentinel-2 imagery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[37.75, -122.45], zoom=12)\n", + "\n", + "collection = (\n", + " ee.ImageCollection('COPERNICUS/S2_SR')\n", + " .filterBounds(ee.Geometry.Point([-122.45, 37.75]))\n", + " .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10)\n", + ")\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "\n", + "Map.add_time_slider(collection, vis_params)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 2 - Creating land cover maps with a legend\n", + "\n", + "Create a split map for visualizing NLCD land cover change in Texas between 2001 and 2019. Add the NLCD legend to the map. Relevant Earth Engine assets:\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"USGS/NLCD_RELEASES/2019_REL/NLCD\")](https://developers.google.com/earth-engine/datasets/catalog/USGS_NLCD_RELEASES_2019_REL_NLCD)\n", + "\n", + "\n", + "![](https://i.imgur.com/LJmztTd.png)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyzing Earth Engine data (30 mins)\n", + "\n", + "### Image descriptive statistics\n", + "\n", + "Use a sample Landsat image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "centroid = ee.Geometry.Point([-122.4439, 37.7538])\n", + "image = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR').filterBounds(centroid).first()\n", + "vis = {'min': 0, 'max': 3000, 'bands': ['B5', 'B4', 'B3']}\n", + "\n", + "Map.centerObject(centroid, 8)\n", + "Map.addLayer(image, vis, \"Landsat-8\")\n", + "Map.addLayer(centroid, {}, 'Centroid')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.propertyNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image property values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.toDictionary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get specific image properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image.get('CLOUD_COVER') # 0.05" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get image properties with easy-to-read time format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "props = geemap.image_props(image)\n", + "props" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute image descriptive statistics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats(image, scale=30)\n", + "stats" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Zonal statistics\n", + "\n", + "#### Zonal statistics\n", + "\n", + "Add Earth Engine data to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NASA SRTM\n", + "dem = ee.Image('USGS/SRTMGL1_003')\n", + "dem_vis = {\n", + " 'min': 0,\n", + " 'max': 4000,\n", + " 'palette': ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5'],\n", + "}\n", + "Map.addLayer(dem, dem_vis, 'SRTM DEM')\n", + "\n", + "# Add 5-year Landsat TOA composite\n", + "landsat = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')\n", + "landsat_vis = {'bands': ['B4', 'B3', 'B2'], 'gamma': 1.4}\n", + "Map.addLayer(landsat, landsat_vis, \"Landsat\", False)\n", + "\n", + "# Add US Census States\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(states.style(**style), {}, 'US States')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics. In this case, we compute the mean elevation of each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_dem_stats = 'dem_stats.csv'\n", + "geemap.zonal_stats(\n", + " dem, states, out_dem_stats, stat_type='MEAN', scale=1000, return_fc=False\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the csv file as a table." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_dem_stats).sort_values(by=['mean'], ascending=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics of mean spectral values of each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "out_landsat_stats = 'landsat_stats.csv'\n", + "geemap.zonal_stats(\n", + " landsat,\n", + " states,\n", + " out_landsat_stats,\n", + " stat_type='MEAN',\n", + " scale=1000,\n", + " return_fc=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(out_landsat_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by group\n", + "\n", + "Compute zonal statistics by group. In this case, we compute the area of each land cover type in each state and export the results to a CSV file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "\n", + "# Add NLCD data\n", + "dataset = ee.Image('USGS/NLCD_RELEASES/2019_REL/NLCD/2019')\n", + "landcover = dataset.select('landcover')\n", + "Map.addLayer(landcover, {}, 'NLCD 2019')\n", + "\n", + "# Add US census states\n", + "states = ee.FeatureCollection(\"TIGER/2018/States\")\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(states.style(**style), {}, 'US States')\n", + "\n", + "# Add NLCD legend\n", + "Map.add_legend(title='NLCD Land Cover', builtin_legend='NLCD')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by group and convert the area unit from square meters to square kilometers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the percentage of each land cover type in each state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "nlcd_stats = 'nlcd_stats_pct.csv'\n", + "\n", + "geemap.zonal_stats_by_group(\n", + " landcover,\n", + " states,\n", + " nlcd_stats,\n", + " stat_type='PERCENTAGE',\n", + " denominator=1e6,\n", + " decimal_places=2,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics with two images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df(nlcd_stats)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by zone\n", + "\n", + "The zonal statistics by zone algorithm is similar to the zonal statistics by group algorithm, but it takes an image as the zone input instead of a feature collection. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "dem = ee.Image('USGS/3DEP/10m')\n", + "vis = {'min': 0, 'max': 4000, 'palette': 'terrain'}\n", + "Map.addLayer(dem, vis, 'DEM')\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "landcover = ee.Image(\"USGS/NLCD_RELEASES/2019_REL/NLCD/2019\").select('landcover')\n", + "Map.addLayer(landcover, {}, 'NLCD 2019')\n", + "Map.add_legend(title='NLCD Land Cover Classification', builtin_legend='NLCD')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Computer the mean elevation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats = geemap.image_stats_by_zone(dem, landcover, reducer='MEAN')\n", + "stats" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "stats.to_csv('mean.csv', index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute the standard deviation of each land cover type." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.image_stats_by_zone(dem, landcover, out_csv=\"std.csv\", reducer='STD')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.csv_to_df('std.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3 - Zonal statistics\n", + "\n", + "Find out which state has the highest mean temperature on in the United States on June 28, 2023. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.ImageCollection(\"NOAA/GFS0P25\")](https://developers.google.com/earth-engine/datasets/catalog/NOAA_GFS0P25)\n", + "\n", + "![](https://i.imgur.com/GZCHHz3.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Coordinate grids and fishnets\n", + "\n", + "#### Creating coordinate grids\n", + "\n", + "Create a latitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lat_grid = geemap.latitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(lat_grid.style(**style), {}, 'Latitude Grid')\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(lat_grid)\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a longitudinal grid with a 5-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lon_grid = geemap.longitude_grid(step=5.0, west=-180, east=180, south=-85, north=85)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(lon_grid.style(**style), {}, 'Longitude Grid')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a rectangular grid with a 10-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "grid = geemap.latlon_grid(\n", + " lat_step=10, lon_step=10, west=-180, east=180, south=-85, north=85\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "style = {'fillColor': '00000000'}\n", + "Map.addLayer(grid.style(**style), {}, 'Coordinate Grid')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Creating fishnets\n", + "\n", + "Create a fishnet based on an Earth Engine geometry." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the drawing tools to draw a polygon on the map above. If no polygon is drawn, the default polygon will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-112.8089, 33.7306, -88.5951, 46.6244)\n", + " Map.addLayer(roi, {}, 'ROI')\n", + " Map.user_roi = None\n", + "\n", + "Map.centerObject(roi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with a 2-degree interval." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, h_interval=2.0, v_interval=2.0, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a new map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Draw a polygon on the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "\n", + "if roi is None:\n", + " roi = ee.Geometry.Polygon(\n", + " [\n", + " [\n", + " [-64.602356, -1.127399],\n", + " [-68.821106, -12.625598],\n", + " [-60.647278, -22.498601],\n", + " [-47.815247, -21.111406],\n", + " [-43.860168, -8.913564],\n", + " [-54.582825, -0.775886],\n", + " [-60.823059, 0.454555],\n", + " [-64.602356, -1.127399],\n", + " ]\n", + " ]\n", + " )\n", + " Map.addLayer(roi, {}, 'ROI')\n", + "\n", + "Map.centerObject(roi)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a fishnet based on a user-drawn polygon with specified number of rows and columns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(roi, rows=6, cols=8, delta=1)\n", + "style = {'color': 'blue', 'fillColor': '00000000'}\n", + "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Land use and land cover change analysis\n", + "\n", + "#### Forest cover mapping\n", + "\n", + "We will use the [Hansen Global Forest Change v1.10 (2000-2022) dataset](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = ee.Image('UMD/hansen/global_forest_change_2022_v1_10')\n", + "dataset.bandNames()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "first_bands = ['first_b50', 'first_b40', 'first_b30']\n", + "first_image = dataset.select(first_bands)\n", + "Map.addLayer(first_image, {'bands': first_bands, 'gamma': 1.5}, 'Year 2000 Bands 5/4/3')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the imagery for 2022." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_bands = ['last_b50', 'last_b40', 'last_b30']\n", + "last_image = dataset.select(last_bands)\n", + "Map.addLayer(last_image, {'bands': last_bands, 'gamma': 1.5}, 'Year 2022 Bands 5/4/3')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select the tree cover imagery for 2000." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "treecover = dataset.select(['treecover2000'])\n", + "treeCoverVisParam = {'min': 0, 'max': 100, 'palette': ['black', 'green']}\n", + "name = 'Tree cover (%)'\n", + "Map.addLayer(treecover, treeCoverVisParam, name)\n", + "Map.add_colorbar(treeCoverVisParam, label=name, layer_name=name)\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Extract tree cover 2000 by using the threshold of 10%." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "threshold = 10\n", + "treecover_bin = treecover.gte(threshold).selfMask()\n", + "treeVisParam = {'palette': ['green']}\n", + "Map.addLayer(treecover_bin, treeVisParam, 'Tree cover bin')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Forest loss and gain mapping\n", + "\n", + "Visualize forest loss." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.add_basemap('Google Hybrid')\n", + "treeloss_year = dataset.select(['lossyear'])\n", + "treeLossVisParam = {'min': 0, 'max': 22, 'palette': ['yellow', 'red']}\n", + "layer_name = 'Tree loss year since 2000'\n", + "Map.addLayer(treeloss_year, treeLossVisParam, layer_name)\n", + "Map.add_colorbar(treeLossVisParam, label=layer_name, layer_name=layer_name)\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare forest loss and gain." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.add_basemap('Google Hybrid')\n", + "treeloss = dataset.select(['loss']).selfMask()\n", + "treegain = dataset.select(['gain']).selfMask()\n", + "Map.addLayer(treeloss, {'palette': 'red'}, 'Tree loss')\n", + "Map.addLayer(treegain, {'palette': 'yellow'}, 'Tree gain')\n", + "Map.add_layer_manager()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Zonal statistics by country\n", + "\n", + "Compute zonal statistics to find out which country has the largest forest area in 2000.\n", + "\n", + "Add a country boundary layer to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "countries = ee.FeatureCollection(geemap.examples.get_ee_path('countries'))\n", + "style = {'color': '#000000ff', 'fillColor': '#00000000'}\n", + "Map.addLayer(countries.style(**style), {}, 'Countries')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute zonal statistics by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treecover_bin,\n", + " countries,\n", + " 'forest_cover.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a pie chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart(\n", + " 'forest_cover.csv', names='NAME', values='sum', max_rows=20, height=400\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'forest_cover.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.zonal_stats(\n", + " treeloss.gt(0),\n", + " countries,\n", + " 'treeloss.csv',\n", + " stat_type='SUM',\n", + " denominator=1e6,\n", + " scale=1000,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.pie_chart('treeloss.csv', names='NAME', values='sum', max_rows=20, height=600)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a bar chart to visualize the forest loss area by country." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.bar_chart(\n", + " 'treeloss.csv',\n", + " x='NAME',\n", + " y='sum',\n", + " max_rows=20,\n", + " x_label='Country',\n", + " y_label='Forest loss area (km2)',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4 - Analyzing forest cover gain and loss\n", + "\n", + "Find out which US state has the largest forest gain and loss between 2000 and 2022. Create pie charts and bar charts to show the results. Relevant Earth Engine assets:\n", + "\n", + "- [ee.FeatureCollection(\"TIGER/2018/States\")](https://developers.google.com/earth-engine/datasets/catalog/TIGER_2018_States)\n", + "- [ee.Image(\"UMD/hansen/global_forest_change_2022_v1_10\")](https://developers.google.com/earth-engine/datasets/catalog/UMD_hansen_global_forest_change_2022_v1_10)\n", + "\n", + "![](https://i.imgur.com/t5sH5ku.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Break 2 (10 mins)\n", + "\n", + "## Exporting Earth Engine data (30 mins)\n", + "\n", + "### Exporting images\n", + "\n", + "Add a Landsat image to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(\n", + " ['B5', 'B4', 'B3']\n", + ")\n", + "\n", + "vis_params = {'min': 0, 'max': 0.5, 'gamma': [0.95, 1.1, 1]}\n", + "\n", + "Map.centerObject(image)\n", + "Map.addLayer(image, vis_params, 'Landsat')\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a rectangle to the map." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = ee.Geometry.BBox(-122.5955, 37.5339, -122.0982, 37.8252)\n", + "fc = ee.FeatureCollection(region)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "Map.addLayer(fc.style(**style), {}, 'ROI')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(image, filename=\"landsat.tif\", scale=30, region=region)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check image projection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "projection = image.select(0).projection().getInfo()\n", + "projection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "crs = projection['crs']\n", + "crs_transform = projection['transform']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify region, crs, and crs_transform." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image(\n", + " image,\n", + " filename=\"landsat_crs.tif\",\n", + " crs=crs,\n", + " crs_transform=crs_transform,\n", + " region=region,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_to_drive(\n", + " image, description='landsat', folder='export', region=region, scale=30\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting image collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "point = ee.Geometry.Point(-99.2222, 46.7816)\n", + "collection = (\n", + " ee.ImageCollection('USDA/NAIP/DOQQ')\n", + " .filterBounds(point)\n", + " .filterDate('2008-01-01', '2018-01-01')\n", + " .filter(ee.Filter.listContains(\"system:band_names\", \"N\"))\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection.aggregate_array('system:index')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection(collection, out_dir='.', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_image_collection_to_drive(collection, folder='export', scale=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exporting feature collections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "fc = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017').filter(\n", + " ee.Filter.eq('country_na', 'Germany')\n", + ")\n", + "Map.addLayer(fc, {}, \"Germany\")\n", + "Map.centerObject(fc)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To local drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_shp(fc, filename='Germany.shp', selectors=None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector(fc, filename='Germany2.shp')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_geojson(fc, filename='Germany.geojson')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_to_csv(fc, filename='Germany.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdf = geemap.ee_to_gdf(fc)\n", + "gdf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = geemap.ee_to_df(fc)\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To Google Drive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.ee_export_vector_to_drive(\n", + " fc, description=\"germany\", fileFormat='SHP', folder=\"export\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 5 - Exporting images by a fishnet\n", + "\n", + "Create a fishnet with a 4-degree interval based on the extent of `[-112.5439, 34.0891, -85.0342, 49.6858]`. Use the fishnet to download the Landsat 7 image tiles by the fishnet using the `geemap.download_ee_image_tiles()` and `geemap.download_ee_image_tiles_parallel()` functions. Relevant Earth Engine assets:\n", + "\n", + "- `ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003')`\n", + "\n", + "![](https://i.imgur.com/L1IH3fq.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003').select(['B4', 'B3', 'B2'])\n", + "Map.addLayer(image, {'min': 20, 'max': 200, 'gamma': 2.0}, 'Landsat')\n", + "region = ee.Geometry.BBox(-112.5439, 34.0891, -85.0342, 49.6858)\n", + "Map.addLayer(region, {}, 'ROI')\n", + "Map.centerObject(region)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fishnet = geemap.fishnet(region, h_interval=4.0, v_interval=4.0, delta=0.5)\n", + "style = {'color': 'ffff00ff', 'fillColor': '00000000'}\n", + "Map.addLayer(fishnet.style(**style), {}, 'Fishnet')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.download_ee_image_tiles(\n", + " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "geemap.download_ee_image_tiles_parallel(\n", + " image, fishnet, out_dir='tiles', scale=1000, crs='EPSG:3857'\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## Creating Satellite timelapse animations (30 mins)\n", + "\n", + "### Creating satellite timeseries\n", + "\n", + "Use the [Harmonized Sentinel-2 MSI](https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_HARMONIZED) dataset to create a timeseries for a given location. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = ee.ImageCollection(\"COPERNICUS/S2_HARMONIZED\").filterMetadata(\n", + " 'CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify the location of interest and date range." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "start_date = '2016-01-01'\n", + "end_date = '2022-12-31'\n", + "region = ee.Geometry.BBox(-122.5549, 37.6968, -122.3446, 37.8111)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an annual composite." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "images = geemap.create_timeseries(\n", + " collection, start_date, end_date, region, frequency='year', reducer='median'\n", + ")\n", + "images" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the timeseries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "\n", + "vis_params = {\"min\": 0, \"max\": 4000, \"bands\": [\"B8\", \"B4\", \"B3\"]}\n", + "labels = [str(y) for y in range(2016, 2023)]\n", + "\n", + "Map.addLayer(images, vis_params, \"Sentinel-2\", False)\n", + "Map.add_time_slider(images, vis_params, time_interval=2, labels=labels)\n", + "Map.centerObject(region)\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating satellite timelapse animations\n", + "\n", + "#### NAIP timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map(center=[40, -100], zoom=4)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-99.1019, 47.1274, -99.0334, 47.1562)\n", + " Map.addLayer(roi, {}, 'ROI')\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "collection = geemap.naip_timeseries(roi, start_year=2009, end_year=2022, RGBN=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "years = geemap.image_dates(collection, date_format='YYYY').getInfo()\n", + "print(years)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "size = len(years)\n", + "images = collection.toList(size)\n", + "for i in range(size):\n", + " image = ee.Image(images.get(i))\n", + " Map.addLayer(image, {'bands': ['N', 'R', 'G']}, years[i])\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.naip_timelapse(\n", + " roi,\n", + " out_gif=\"naip.gif\",\n", + " bands=['N', 'R', 'G'],\n", + " frames_per_second=3,\n", + " title='NAIP Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Landsat timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='landsat.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=5,\n", + " title='Landsat Timelapse',\n", + " progress_bar_color='blue',\n", + " mp4=True,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "roi = ee.Geometry.BBox(-115.5541, 35.8044, -113.9035, 36.5581)\n", + "Map.addLayer(roi)\n", + "Map.centerObject(roi)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='las_vegas.gif',\n", + " start_year=1984,\n", + " end_year=2022,\n", + " bands=['NIR', 'Red', 'Green'],\n", + " frames_per_second=5,\n", + " title='Las Vegas, NV',\n", + " font_color='blue',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "roi = ee.Geometry.BBox(113.8252, 22.1988, 114.0851, 22.3497)\n", + "Map.addLayer(roi)\n", + "Map.centerObject(roi)\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.landsat_timelapse(\n", + " roi,\n", + " out_gif='hong_kong.gif',\n", + " start_year=1990,\n", + " end_year=2022,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Hong Kong',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sentinel-2 timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pan and zoom the map to an area of interest. Use the drawing tools to draw a rectangle on the map. If no rectangle is drawn, the default rectangle shown below will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-74.7222, -8.5867, -74.1596, -8.2824)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.sentinel2_timelapse(\n", + " roi,\n", + " out_gif='sentinel2.gif',\n", + " start_year=2016,\n", + " end_year=2021,\n", + " start_date='01-01',\n", + " end_date='12-31',\n", + " frequency='year',\n", + " bands=['SWIR1', 'NIR', 'Red'],\n", + " frames_per_second=3,\n", + " title='Sentinel-2 Timelapse',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### MODIS timelapse\n", + "\n", + "MODIS vegetation indices" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-18.6983, -36.1630, 52.2293, 38.1446)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ndvi_timelapse(\n", + " roi,\n", + " out_gif='ndvi.gif',\n", + " data='Terra',\n", + " band='NDVI',\n", + " start_date='2000-01-01',\n", + " end_date='2022-12-31',\n", + " frames_per_second=3,\n", + " title='MODIS NDVI Timelapse',\n", + " overlay_data='countries',\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MODIS temperature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = Map.user_roi\n", + "if roi is None:\n", + " roi = ee.Geometry.BBox(-171.21, -57.13, 177.53, 79.99)\n", + " Map.addLayer(roi)\n", + " Map.centerObject(roi)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.modis_ocean_color_timelapse(\n", + " satellite='Aqua',\n", + " start_date='2018-01-01',\n", + " end_date='2020-12-31',\n", + " roi=roi,\n", + " frequency='month',\n", + " out_gif='temperature.gif',\n", + " overlay_data='continents',\n", + " overlay_color='yellow',\n", + " overlay_opacity=0.5,\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### GOES timelapse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(167.1898, -28.5757, 202.6258, -12.4411)\n", + "start_date = \"2022-01-15T03:00:00\"\n", + "end_date = \"2022-01-15T07:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"goes.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-159.5954, 24.5178, -114.2438, 60.4088)\n", + "start_date = \"2021-10-24T14:00:00\"\n", + "end_date = \"2021-10-25T01:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_timelapse(\n", + " roi, \"hurricane.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "roi = ee.Geometry.BBox(-121.0034, 36.8488, -117.9052, 39.0490)\n", + "start_date = \"2020-09-05T15:00:00\"\n", + "end_date = \"2020-09-06T02:00:00\"\n", + "data = \"GOES-17\"\n", + "scan = \"full_disk\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "timelapse = geemap.goes_fire_timelapse(\n", + " roi, \"fire.gif\", start_date, end_date, data, scan, framesPerSecond=5\n", + ")\n", + "geemap.show_image(timelapse)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6 - Creating timelapse animations\n", + "\n", + "Use the geemap timelapse GUI to create a timelapse animation for any location of your choice. Share the timelapse on social media and use the hashtagd such as #EarthEngine and #geemap. See [this](https://i.imgur.com/uFaXD9s.gif) example.\n", + "\n", + "![](https://i.imgur.com/vecPydF.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Map = geemap.Map()\n", + "Map.add_gui(\"timelapse\")\n", + "Map" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "## Break 3 (10 mins)\n", + "\n", + "## Building interactive web apps (30 mins)\n", + "\n", + "This section is optional. We might not have enough time to cover this section.\n", + "\n", + "Follow the instructions [here](https://huggingface.co/spaces/giswqs/solara-geemap) to build an interactive Earth Engine web app with [Solara](https://github.com/widgetti/solara) and geemap. You need to [sign up](https://huggingface.co/join) for a free Hugging Face account to create the web app. It is free and easy to sign up.\n", + "\n", + "### Exercise 7 - Building an interactive web app for visualizing land cover change\n", + "\n", + "After following the instructions above, you should have a web app that looks like this:\n", + "\n", + "![](https://i.imgur.com/uYDUPl0.png)\n", + "\n", + "The web app URL should look like this: https://giswqs-solara-geemap.hf.space/split-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.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/geemap/chart.py b/geemap/chart.py index 456088a745..1d2e8073c3 100644 --- a/geemap/chart.py +++ b/geemap/chart.py @@ -12,7 +12,7 @@ from bqplot import Tooltip from bqplot import pyplot as plt -from .common import ee_to_df +from .common import ee_to_df, zonal_stats from typing import Union @@ -34,9 +34,13 @@ def __init__(self, features, default_labels, name, **kwargs): self.width = None self.height = None self.colors = "black" - self.df = ee_to_df(features) self.name = name + if isinstance(features, ee.FeatureCollection): + self.df = ee_to_df(features) + elif isinstance(features, pd.DataFrame): + self.df = features + for key, value in kwargs.items(): setattr(self, key, value) diff --git a/geemap/common.py b/geemap/common.py index 2f0ebb1a52..1713a1a969 100644 --- a/geemap/common.py +++ b/geemap/common.py @@ -3337,9 +3337,7 @@ def list_to_ee(a_list): print(e) -def ee_to_numpy( - ee_object, region=None, scale=None, bands=None, **kwargs -): +def ee_to_numpy(ee_object, region=None, scale=None, bands=None, **kwargs): """Extracts a rectangular region of pixels from an image into a numpy array. Args: @@ -3356,10 +3354,10 @@ def ee_to_numpy( if (region is not None) or (scale is not None): ee_object = ee_object.clipToBoundsAndScale(geometry=region, scale=scale) - kwargs['expression'] = ee_object - kwargs['fileFormat'] = 'NUMPY_NDARRAY' + kwargs["expression"] = ee_object + kwargs["fileFormat"] = "NUMPY_NDARRAY" if bands is not None: - kwargs['bandIds'] = bands + kwargs["bandIds"] = bands try: struct_array = ee.data.computePixels(kwargs) @@ -6714,7 +6712,7 @@ def zonal_stats( in_value_raster, in_zone_vector, out_file_path=None, - statistics_type="MEAN", + stat_type="MEAN", scale=None, crs=None, tile_scale=1.0, @@ -6730,7 +6728,7 @@ def zonal_stats( in_value_raster (object): An ee.Image or ee.ImageCollection that contains the values on which to calculate a statistic. in_zone_vector (object): An ee.FeatureCollection that defines the zones. out_file_path (str): Output file path that will contain the summary of the values in each zone. The file type can be: csv, shp, json, kml, kmz - statistics_type (str, optional): Statistic type to be calculated. Defaults to 'MEAN'. For 'HIST', you can provide three parameters: max_buckets, min_bucket_width, and max_raw. For 'FIXED_HIST', you must provide three parameters: hist_min, hist_max, and hist_steps. + stat_type (str, optional): Statistical type to be calculated. Defaults to 'MEAN'. For 'HIST', you can provide three parameters: max_buckets, min_bucket_width, and max_raw. For 'FIXED_HIST', you must provide three parameters: hist_min, hist_max, and hist_steps. scale (float, optional): A nominal scale in meters of the projection to work in. Defaults to None. crs (str, optional): The projection to work in. If unspecified, the projection of the image's first band is used. If specified in addition to scale, rescaled to the specified scale. Defaults to None. tile_scale (float, optional): A scaling factor used to reduce aggregation tile size; using a larger tileScale (e.g. 2 or 4) may enable computations that run out of memory with the default. Defaults to 1.0. @@ -6754,6 +6752,10 @@ def zonal_stats( if out_file_path is None: out_file_path = os.path.join(os.getcwd(), "zonal_stats.csv") + if "statistics_type" in kwargs: + stat_type = kwargs["statistics_type"] + kwargs.pop("statistics_type") + allowed_formats = ["csv", "geojson", "kml", "kmz", "shp"] filename = os.path.abspath(out_file_path) basename = os.path.basename(filename) @@ -6786,20 +6788,21 @@ def zonal_stats( if "max_raw" in kwargs.keys(): max_raw = kwargs["max_raw"] - if ( - statistics_type.upper() == "FIXED_HIST" - and ("hist_min" in kwargs.keys()) - and ("hist_max" in kwargs.keys()) - and ("hist_steps" in kwargs.keys()) - ): - hist_min = kwargs["hist_min"] - hist_max = kwargs["hist_max"] - hist_steps = kwargs["hist_steps"] - elif statistics_type.upper() == "FIXED_HIST": - print( - "To use fixedHistogram, please provide these three parameters: hist_min, hist_max, and hist_steps." - ) - return + if isinstance(stat_type, str): + if ( + stat_type.upper() == "FIXED_HIST" + and ("hist_min" in kwargs.keys()) + and ("hist_max" in kwargs.keys()) + and ("hist_steps" in kwargs.keys()) + ): + hist_min = kwargs["hist_min"] + hist_max = kwargs["hist_max"] + hist_steps = kwargs["hist_steps"] + elif stat_type.upper() == "FIXED_HIST": + print( + "To use fixedHistogram, please provide these three parameters: hist_min, hist_max, and hist_steps." + ) + return allowed_statistics = { "COUNT": ee.Reducer.count(), @@ -6825,13 +6828,19 @@ def zonal_stats( ), } - if not (statistics_type.upper() in allowed_statistics.keys()): - print( - "The statistics type must be one of the following: {}".format( - ", ".join(list(allowed_statistics.keys())) + if isinstance(stat_type, str): + if not (stat_type.upper() in allowed_statistics.keys()): + print( + "The statistics type must be one of the following: {}".format( + ", ".join(list(allowed_statistics.keys())) + ) ) - ) - return + return + reducer = allowed_statistics[stat_type.upper()] + elif isinstance(stat_type, ee.Reducer): + reducer = stat_type + else: + raise ValueError("statistics_type must be either a string or ee.Reducer.") if scale is None: scale = in_value_raster.projection().nominalScale().multiply(10) @@ -6841,7 +6850,7 @@ def zonal_stats( print("Computing statistics ...") result = in_value_raster.reduceRegions( collection=in_zone_vector, - reducer=allowed_statistics[statistics_type], + reducer=reducer, scale=scale, crs=crs, tileScale=tile_scale, @@ -6856,12 +6865,11 @@ def zonal_stats( zonal_statistics = zonal_stats - def zonal_stats_by_group( in_value_raster, in_zone_vector, out_file_path=None, - statistics_type="SUM", + stat_type="SUM", decimal_places=0, denominator=1.0, scale=None, @@ -6882,7 +6890,7 @@ def zonal_stats_by_group( in_value_raster (object): An integer Image that contains the values on which to calculate area/percentage. in_zone_vector (object): An ee.FeatureCollection that defines the zones. out_file_path (str): Output file path that will contain the summary of the values in each zone. The file type can be: csv, shp, json, kml, kmz - statistics_type (str, optional): Can be either 'SUM' or 'PERCENTAGE' . Defaults to 'SUM'. + stat_type (str, optional): Can be either 'SUM' or 'PERCENTAGE' . Defaults to 'SUM'. decimal_places (int, optional): The number of decimal places to use. Defaults to 0. denominator (float, optional): To convert area units (e.g., from square meters to square kilometers). Defaults to 1.0. scale (float, optional): A nominal scale in meters of the projection to work in. Defaults to None. @@ -6908,6 +6916,10 @@ def zonal_stats_by_group( if out_file_path is None: out_file_path = os.path.join(os.getcwd(), "zonal_stats_by_group.csv") + if "statistics_type" in kwargs: + stat_type = kwargs["statistics_type"] + kwargs.pop("statistics_type") + band_count = in_value_raster.bandNames().size().getInfo() band_name = "" @@ -6946,7 +6958,7 @@ def zonal_stats_by_group( os.makedirs(out_dir) allowed_statistics = ["SUM", "PERCENTAGE"] - if not (statistics_type.upper() in allowed_statistics): + if not (stat_type.upper() in allowed_statistics): print( "The statistics type can only be one of {}".format( ", ".join(allowed_statistics) @@ -7032,7 +7044,7 @@ def get_class_values(x): keys.contains(x), values.get(keys.indexOf(x)), 0 ) cls_value = ee.Algorithms.If( - ee.String(statistics_type).compareTo(ee.String("SUM")), + ee.String(stat_type).compareTo(ee.String("SUM")), ee.Number(cls_value).divide(ee.Number(total_area)), cls_value, )