diff --git a/code/end_to_end_gee/01_python_api_syntax.ipynb b/code/end_to_end_gee/01_python_api_syntax.ipynb index a925ad4c..5172d5bd 100644 --- a/code/end_to_end_gee/01_python_api_syntax.ipynb +++ b/code/end_to_end_gee/01_python_api_syntax.ipynb @@ -1,385 +1,385 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "FG8qKXC42iLk" - }, - "source": [ - "Coming from the programming in Earth Engine through the Code Editor, you will need to slightly adapt your scripts to be able to run in Python. For the bulk of your code, you will be using Earth Engine API's server-side objects and functions - which will be exactly the same in Python. You only need to make a few syntactical changes.\n", - "\n", - "[Here's the full list](https://developers.google.com/earth-engine/python_install#syntax) of differences." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "CpVwpjkjIAJQ" - }, - "source": [ - "#### Initialization\n", - "\n", - "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/).\n", - "\n", - "You will be prompted to allow the notebook to access your Google credentials to sign-in to the account and allow access to *Google Drive and Google Cloud data*. Once you approve, it will proceed to initialize the Earth Engine API. This step needs to be done just once per session." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "id": "Nv3V91tF2iLX" - }, - "outputs": [], - "source": [ - "import ee" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "id": "gjRJhBKF2iLf" - }, - "outputs": [], - "source": [ - "cloud_project = 'spatialthoughts'\n", - "\n", - "try:\n", - " ee.Initialize(project=cloud_project)\n", - "except:\n", - " ee.Authenticate()\n", - " ee.Initialize(project=cloud_project)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "VcKwp3Qw2iLl" - }, - "source": [ - "#### Variables\n", - "\n", - "Python code doesn't use the 'var' keyword\n", - "\n", - "javascript code:\n", - "```\n", - "var city = 'San Fransico'\n", - "var state = 'California'\n", - "print(city, state)\n", - "\n", - "var population = 881549\n", - "print(population)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "dyH3WyF92iLm" - }, - "outputs": [], - "source": [ - "city = 'San Fransico'\n", - "state = 'California'\n", - "print(city, state)\n", - "\n", - "population = 881549\n", - "print(population)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5WClkHCBIAJT" - }, - "source": [ - "#### Earth Engine Objects\n", - "\n", - "You can create Earth Engine objects using the ``ee`` functions the same way." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "JCq8eiTjIAJU" - }, - "outputs": [], - "source": [ - "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", - "geometry = ee.Geometry.Polygon([[\n", - " [82.60642647743225, 27.16350437805251],\n", - " [82.60984897613525, 27.1618529901377],\n", - " [82.61088967323303, 27.163695288375266],\n", - " [82.60757446289062, 27.16517483230927]\n", - "]])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "349JPCj12iLv" - }, - "source": [ - "#### Line Continuation\n", - "\n", - "Python doesn't use a semi-colon for line ending. To indicate line-continuation you need to use the \\\\ character\n", - "\n", - "javascript code:\n", - "```\n", - "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", - "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", - " .filter(ee.Filter.date('2019-02-01', '2019-03-01'))\n", - " .filter(ee.Filter.bounds(geometry));\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "uZwEVx5c2iLw" - }, - "outputs": [], - "source": [ - "filtered = s2 \\\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", - " .filter(ee.Filter.date('2019-02-01', '2019-03-01')) \\\n", - " .filter(ee.Filter.bounds(geometry))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "qpHepM3Q2iL0" - }, - "source": [ - "#### Functions\n", - "\n", - "Instead of the `function` keyword, Python uses the `def` keyword. Also the in-line functions are defined using `lambda` anonymous functions.\n", - "\n", - "In the example below, also now the `and` operator - which is capitalized as `And` in Python version to avoid conflict with the built-in `and` operator. The same applies to `Or` and `Not` operators. `true`, `false`, `null` in Python are also spelled as `True`, `False` and `None`.\n", - "\n", - "javascript code:\n", - "```\n", - "function maskS2clouds(image) {\n", - " var qa = image.select('QA60')\n", - " var cloudBitMask = 1 << 10;\n", - " var cirrusBitMask = 1 << 11;\n", - " var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(\n", - " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", - " return image.updateMask(mask)//.divide(10000)\n", - " .select(\"B.*\")\n", - " .copyProperties(image, [\"system:time_start\"])\n", - "}\n", - "\n", - "function addNDVI(image) {\n", - " var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');\n", - " return image.addBands(ndvi);\n", - "}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "bRbMb8B02iL2" - }, - "outputs": [], - "source": [ - "def maskS2clouds(image):\n", - " qa = image.select('QA60')\n", - " cloudBitMask = 1 << 10\n", - " cirrusBitMask = 1 << 11\n", - " mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(\n", - " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", - " return image.updateMask(mask) \\\n", - " .select(\"B.*\") \\\n", - " .copyProperties(image, [\"system:time_start\"])\n", - "\n", - "def addNDVI(image):\n", - " ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi')\n", - " return image.addBands(ndvi)\n", - "\n", - "withNdvi = filtered \\\n", - " .map(maskS2clouds) \\\n", - " .map(addNDVI)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "x6E1D2hv2iL8" - }, - "source": [ - "#### Function Arguments\n", - "\n", - "Named arguments to Earth Engine functions need to be in quotes. Also when passing the named arguments as a dictionary, it needs to be passed using the `**` keyword.\n", - "\n", - "javascript code:\n", - "```\n", - "var composite = withNdvi.median();\n", - "var ndvi = composite.select('ndvi');\n", - "\n", - "var stats = ndvi.reduceRegion({\n", - " reducer: ee.Reducer.mean(),\n", - " geometry: geometry,\n", - " scale: 10,\n", - " maxPixels: 1e10\n", - "}) \n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "y3hGC4wwIAJW" - }, - "outputs": [], - "source": [ - "composite = withNdvi.median()\n", - "ndvi = composite.select('ndvi')\n", - "\n", - "stats = ndvi.reduceRegion(**{\n", - " 'reducer': ee.Reducer.mean(),\n", - " 'geometry': geometry,\n", - " 'scale': 10,\n", - " 'maxPixels': 1e10\n", - " })" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "bYzscid52iMM", - "tags": [] - }, - "source": [ - "#### Printing Values\n", - "\n", - "The `print()` function syntax is the same. But you must remember that in the Code Editor when you cann `print`, the value of the server object is fetched and then printed. You must do that explicitely by calling `getInfo()` on any server-side object.\n", - "\n", - "javascript code:\n", - "```\n", - "print(stats.get('ndvi')\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "SXVG1s-92iMA" - }, - "outputs": [], - "source": [ - "print(stats.get('ndvi').getInfo())" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "S8U09l6E2iME" - }, - "source": [ - "#### In-line functions\n", - "\n", - "The syntax for defining in-line functions is also slightly different. You need to use the `lambda` keyword.\n", - "\n", - "javascript code:\n", - "```\n", - "var myList = ee.List.sequence(1, 10);\n", - "var newList = myList.map(function(number) {\n", - " return ee.Number(number).pow(2);\n", - "print(newList);\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "eC1intbg2iMF" - }, - "outputs": [], - "source": [ - "myList = ee.List.sequence(1, 10)\n", - "newList = myList.map(lambda number: ee.Number(number).pow(2))\n", - "print(newList.getInfo())" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5nx9qiWrIAJX" - }, - "source": [ - "### Exercise\n", - "\n", - "Take the Javascript code snippet below and write the equiavalent Python code in the cell below.\n", - "\n", - "- **Hint1**: Chaining of filters require the use of line continuation character `\\`\n", - "- **Hint2**: Printing of server-side objects requires calling `.getInfo()` on the object\n", - "\n", - "The correct code should print the value **30**.\n", - "\n", - "---\n", - "\n", - "```\n", - "var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]);\n", - "\n", - "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", - "\n", - "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", - " .filter(ee.Filter.date('2019-01-01', '2020-01-01'))\n", - " .filter(ee.Filter.bounds(geometry));\n", - " \n", - "print(filtered.size());\n", - "```\n", - "---" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "ImEsqdU1IAJX" - }, - "outputs": [], - "source": [ - "import ee\n", - "ee.Authenticate()\n", - "ee.Initialize()" - ] - } - ], - "metadata": { - "colab": { - "name": "01_syntax.ipynb", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "FG8qKXC42iLk" + }, + "source": [ + "Coming from the programming in Earth Engine through the Code Editor, you will need to slightly adapt your scripts to be able to run in Python. For the bulk of your code, you will be using Earth Engine API's server-side objects and functions - which will be exactly the same in Python. You only need to make a few syntactical changes.\n", + "\n", + "[Here's the full list](https://developers.google.com/earth-engine/python_install#syntax) of differences." + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "markdown", + "metadata": { + "id": "CpVwpjkjIAJQ" + }, + "source": [ + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/).\n", + "\n", + "You will be prompted to allow the notebook to access your Google credentials to sign-in to the account and allow access to *Google Drive and Google Cloud data*. Once you approve, it will proceed to initialize the Earth Engine API. This step needs to be done just once per session." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Nv3V91tF2iLX" + }, + "outputs": [], + "source": [ + "import ee" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gjRJhBKF2iLf" + }, + "outputs": [], + "source": [ + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VcKwp3Qw2iLl" + }, + "source": [ + "#### Variables\n", + "\n", + "Python code doesn't use the 'var' keyword\n", + "\n", + "javascript code:\n", + "```\n", + "var city = 'San Fransico'\n", + "var state = 'California'\n", + "print(city, state)\n", + "\n", + "var population = 881549\n", + "print(population)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "dyH3WyF92iLm" + }, + "outputs": [], + "source": [ + "city = 'San Fransico'\n", + "state = 'California'\n", + "print(city, state)\n", + "\n", + "population = 881549\n", + "print(population)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5WClkHCBIAJT" + }, + "source": [ + "#### Earth Engine Objects\n", + "\n", + "You can create Earth Engine objects using the ``ee`` functions the same way." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "JCq8eiTjIAJU" + }, + "outputs": [], + "source": [ + "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", + "geometry = ee.Geometry.Polygon([[\n", + " [82.60642647743225, 27.16350437805251],\n", + " [82.60984897613525, 27.1618529901377],\n", + " [82.61088967323303, 27.163695288375266],\n", + " [82.60757446289062, 27.16517483230927]\n", + "]])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "349JPCj12iLv" + }, + "source": [ + "#### Line Continuation\n", + "\n", + "Python doesn't use a semi-colon for line ending. To indicate line-continuation you need to use the \\\\ character\n", + "\n", + "javascript code:\n", + "```\n", + "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", + "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", + " .filter(ee.Filter.date('2019-02-01', '2019-03-01'))\n", + " .filter(ee.Filter.bounds(geometry));\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "uZwEVx5c2iLw" + }, + "outputs": [], + "source": [ + "filtered = s2 \\\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", + " .filter(ee.Filter.date('2019-02-01', '2019-03-01')) \\\n", + " .filter(ee.Filter.bounds(geometry))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qpHepM3Q2iL0" + }, + "source": [ + "#### Functions\n", + "\n", + "Instead of the `function` keyword, Python uses the `def` keyword. Also the in-line functions are defined using `lambda` anonymous functions.\n", + "\n", + "In the example below, also now the `and` operator - which is capitalized as `And` in Python version to avoid conflict with the built-in `and` operator. The same applies to `Or` and `Not` operators. `true`, `false`, `null` in Python are also spelled as `True`, `False` and `None`.\n", + "\n", + "javascript code:\n", + "```\n", + "function maskS2clouds(image) {\n", + " var qa = image.select('QA60')\n", + " var cloudBitMask = 1 << 10;\n", + " var cirrusBitMask = 1 << 11;\n", + " var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(\n", + " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", + " return image.updateMask(mask)//.divide(10000)\n", + " .select(\"B.*\")\n", + " .copyProperties(image, [\"system:time_start\"])\n", + "}\n", + "\n", + "function addNDVI(image) {\n", + " var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');\n", + " return image.addBands(ndvi);\n", + "}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "bRbMb8B02iL2" + }, + "outputs": [], + "source": [ + "def maskS2clouds(image):\n", + " qa = image.select('QA60')\n", + " cloudBitMask = 1 << 10\n", + " cirrusBitMask = 1 << 11\n", + " mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(\n", + " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", + " return image.updateMask(mask) \\\n", + " .select(\"B.*\") \\\n", + " .copyProperties(image, [\"system:time_start\"])\n", + "\n", + "def addNDVI(image):\n", + " ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi')\n", + " return image.addBands(ndvi)\n", + "\n", + "withNdvi = filtered \\\n", + " .map(maskS2clouds) \\\n", + " .map(addNDVI)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "x6E1D2hv2iL8" + }, + "source": [ + "#### Function Arguments\n", + "\n", + "Named arguments to Earth Engine functions need to be in quotes. Also when passing the named arguments as a dictionary, it needs to be passed using the `**` keyword.\n", + "\n", + "javascript code:\n", + "```\n", + "var composite = withNdvi.median();\n", + "var ndvi = composite.select('ndvi');\n", + "\n", + "var stats = ndvi.reduceRegion({\n", + " reducer: ee.Reducer.mean(),\n", + " geometry: geometry,\n", + " scale: 10,\n", + " maxPixels: 1e10\n", + "}) \n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "y3hGC4wwIAJW" + }, + "outputs": [], + "source": [ + "composite = withNdvi.median()\n", + "ndvi = composite.select('ndvi')\n", + "\n", + "stats = ndvi.reduceRegion(**{\n", + " 'reducer': ee.Reducer.mean(),\n", + " 'geometry': geometry,\n", + " 'scale': 10,\n", + " 'maxPixels': 1e10\n", + " })" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "bYzscid52iMM", + "tags": [] + }, + "source": [ + "#### Printing Values\n", + "\n", + "The `print()` function syntax is the same. But you must remember that in the Code Editor when you cann `print`, the value of the server object is fetched and then printed. You must do that explicitely by calling `getInfo()` on any server-side object.\n", + "\n", + "javascript code:\n", + "```\n", + "print(stats.get('ndvi')\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "SXVG1s-92iMA" + }, + "outputs": [], + "source": [ + "print(stats.get('ndvi').getInfo())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "S8U09l6E2iME" + }, + "source": [ + "#### In-line functions\n", + "\n", + "The syntax for defining in-line functions is also slightly different. You need to use the `lambda` keyword.\n", + "\n", + "javascript code:\n", + "```\n", + "var myList = ee.List.sequence(1, 10);\n", + "var newList = myList.map(function(number) {\n", + " return ee.Number(number).pow(2);\n", + "print(newList);\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "eC1intbg2iMF" + }, + "outputs": [], + "source": [ + "myList = ee.List.sequence(1, 10)\n", + "newList = myList.map(lambda number: ee.Number(number).pow(2))\n", + "print(newList.getInfo())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5nx9qiWrIAJX" + }, + "source": [ + "### Exercise\n", + "\n", + "Take the Javascript code snippet below and write the equiavalent Python code in the cell below.\n", + "\n", + "- **Hint1**: Chaining of filters require the use of line continuation character `\\`\n", + "- **Hint2**: Printing of server-side objects requires calling `.getInfo()` on the object\n", + "\n", + "The correct code should print the value **30**.\n", + "\n", + "---\n", + "\n", + "```\n", + "var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]);\n", + "\n", + "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", + "\n", + "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", + " .filter(ee.Filter.date('2019-01-01', '2020-01-01'))\n", + " .filter(ee.Filter.bounds(geometry));\n", + " \n", + "print(filtered.size());\n", + "```\n", + "---" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ImEsqdU1IAJX" + }, + "outputs": [], + "source": [ + "import ee\n", + "ee.Authenticate()\n", + "ee.Initialize()" + ] + } + ], + "metadata": { + "colab": { + "name": "01_syntax.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb b/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb index b3a9e5c3..335a567b 100644 --- a/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb +++ b/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb @@ -1,377 +1,377 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "WD-QeVYP2iMT" - }, - "source": [ - "[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python.\n", - "\n", - "It comes with a function that can help you translate your javascript earth engine code to Python automatically.\n", - "\n", - "The `geemap` package is pre-installed in Colab." - ] - }, - { - "cell_type": "code", - "source": [ - "import geemap\n", - "import ee" - ], - "metadata": { - "id": "apXfk7X6Uyz2" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "CpVwpjkjIAJQ" - }, - "source": [ - "#### Initialization\n", - "\n", - "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "gjRJhBKF2iLf" - }, - "outputs": [], - "source": [ - "cloud_project = 'spatialthoughts'\n", - "\n", - "try:\n", - " ee.Initialize(project=cloud_project)\n", - "except:\n", - " ee.Authenticate()\n", - " ee.Initialize(project=cloud_project)" - ] - }, - { - "cell_type": "markdown", - "source": [ - "#### Automatic Conversion using GUI" - ], - "metadata": { - "id": "37jsLQJiZQ3A" - } - }, - { - "cell_type": "markdown", - "source": [ - "`geemap` comes with a user interface that can be used to interactively do code conversion. Let's try to convert the following Javascript code to Python.\n", - "\n", - "```\n", - "var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]);\n", - "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", - "\n", - "var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};\n", - "\n", - "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", - " .filter(ee.Filter.date('2019-01-01', '2020-01-01'))\n", - " .filter(ee.Filter.bounds(geometry));\n", - " \n", - "var medianComposite = filtered.median();\n", - "\n", - "Map.centerObject(geometry, 10);\n", - "Map.addLayer(medianComposite, rgbVis, 'Median Composite');\n", - "```\n", - "\n", - "Run the cell below to load the map widget. Once the map widget loads, click the *Toolbar* icon in the top-right corner and select the *Convert Earth Engine Javascript to Python* tool. Paste your Javascript code and click *Convert*." - ], - "metadata": { - "id": "AEr4OXZuVOp0" - } - }, - { - "cell_type": "code", - "source": [ - "m = geemap.Map(width=800)\n", - "m" - ], - "metadata": { - "id": "tmTgTEA4VaY1" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241])\n", - "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", - "\n", - "rgbVis = {'min': 0.0, 'max': 3000, 'bands': ['B4', 'B3', 'B2']}\n", - "\n", - "filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", - " .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", - " .filter(ee.Filter.bounds(geometry))\n", - "\n", - "medianComposite = filtered.median()\n", - "\n", - "m.centerObject(geometry, 10)\n", - "m.addLayer(medianComposite, rgbVis, 'Median Composite')\n" - ], - "metadata": { - "id": "kGob1XI3aXve" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "You will see the auto-converted code displayed. Copy and paste it into a new cell and run it. Your code will be run using the GEE Python API. If your code loads any layers, they will be loadded on the map widget. To display it, open a new code cell and just type `m` to display the widget.\n", - "\n" - ], - "metadata": { - "id": "AMnk0ZXUXNNL" - } - }, - { - "cell_type": "code", - "source": [ - "m" - ], - "metadata": { - "id": "OeHqXTRRYuui" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "> Note The auto-conversion is almost perfect and works flawlessly on most GEE code. One place it misses is during the conversion of function arguments specified as a dicitonary. You will need to prefix the resulting code with `**` to specify them as `**kwargs`. For example, the `geemap` converter produces code such as below.\n", - " ```\n", - " stats = image.reduceRegion({\n", - " 'reducer': ee.Reducer.mean(),\n", - " 'geometry': geometry,\n", - " 'scale': 10,\n", - " 'maxPixels': 1e10\n", - " })\n", - " ```\n", - "To make this valid GEE Python API code - prefix the argument dictionary with `**`.\n", - " ```\n", - " stats = image.reduceRegion(**{\n", - " 'reducer': ee.Reducer.mean(),\n", - " 'geometry': geometry,\n", - " 'scale': 10,\n", - " 'maxPixels': 1e10\n", - " })\n", - " ```" - ], - "metadata": { - "id": "Yd1eFlklYvr-" - } - }, - { - "cell_type": "markdown", - "source": [ - "#### Automatic Conversion using Code" - ], - "metadata": { - "id": "qfQyzIgpZN1v" - } - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vDE9fRr3KqIK" - }, - "source": [ - "`geemap` offers a function `js_snippet_to_py()` that can be used to perform the conversion using code. This is useful for batch conversions. To use this, we first create a string with the javascript code." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "nxPPLtLI2iMa" - }, - "outputs": [], - "source": [ - "javascript_code = \"\"\"\n", - "var geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766]);\n", - "Map.centerObject(geometry, 12)\n", - "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", - "var rgbVis = {\n", - " min: 0.0,\n", - " max: 3000,\n", - " bands: ['B4', 'B3', 'B2'],\n", - "};\n", - "\n", - "// Write a function for Cloud masking\n", - "function maskS2clouds(image) {\n", - " var qa = image.select('QA60')\n", - " var cloudBitMask = 1 << 10;\n", - " var cirrusBitMask = 1 << 11;\n", - " var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(\n", - " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", - " return image.updateMask(mask)\n", - " .select(\"B.*\")\n", - " .copyProperties(image, [\"system:time_start\"])\n", - "}\n", - "\n", - "var filtered = s2\n", - " .filter(ee.Filter.date('2019-01-01', '2019-12-31'))\n", - " .filter(ee.Filter.bounds(geometry))\n", - " .map(maskS2clouds)\n", - "\n", - "\n", - "// Write a function that computes NDVI for an image and adds it as a band\n", - "function addNDVI(image) {\n", - " var ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi');\n", - " return image.addBands(ndvi);\n", - "}\n", - "\n", - "var withNdvi = filtered.map(addNDVI);\n", - "\n", - "var composite = withNdvi.median()\n", - "palette = [\n", - " 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',\n", - " '74A901', '66A000', '529400', '3E8601', '207401', '056201',\n", - " '004C00', '023B01', '012E01', '011D01', '011301'];\n", - "\n", - "ndviVis = {min:0, max:0.5, palette: palette }\n", - "Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')\n", - "\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "zYsztHh42iMf" - }, - "outputs": [], - "source": [ - "lines = geemap.js_snippet_to_py(\n", - " javascript_code, add_new_cell=False,\n", - " import_ee=True, import_geemap=True, show_map=True)\n", - "for line in lines:\n", - " print(line.rstrip())" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "DMGdvTv3KqIM" - }, - "source": [ - "The automatic conversion works great. Review it and paste it to the cell below." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "OnrJ0KZEKqIN" - }, - "outputs": [], - "source": [ - "import ee\n", - "import geemap\n", - "m = geemap.Map()\n", - "\n", - "geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])\n", - "m.centerObject(geometry, 12)\n", - "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", - "rgbVis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "# Write a function for Cloud masking\n", - "def maskS2clouds(image):\n", - " qa = image.select('QA60')\n", - " cloudBitMask = 1 << 10\n", - " cirrusBitMask = 1 << 11\n", - " mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(\n", - " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", - " return image.updateMask(mask) \\\n", - " .select(\"B.*\") \\\n", - " .copyProperties(image, [\"system:time_start\"])\n", - "\n", - "filtered = s2 \\\n", - " .filter(ee.Filter.date('2019-01-01', '2019-12-31')) \\\n", - " .filter(ee.Filter.bounds(geometry)) \\\n", - " .map(maskS2clouds)\n", - "\n", - "# Write a function that computes NDVI for an image and adds it as a band\n", - "def addNDVI(image):\n", - " ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')\n", - " return image.addBands(ndvi)\n", - "\n", - "withNdvi = filtered.map(addNDVI)\n", - "\n", - "composite = withNdvi.median()\n", - "palette = [\n", - " 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',\n", - " '74A901', '66A000', '529400', '3E8601', '207401', '056201',\n", - " '004C00', '023B01', '012E01', '011D01', '011301']\n", - "\n", - "ndviVis = {'min':0, 'max':0.5, 'palette': palette }\n", - "m.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')\n", - "m" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "SH4cW4iZKqIN" - }, - "source": [ - "### Exercise\n", - "\n", - "Take the Javascript code snippet below and use `geemap` to automatically convert it to Python.\n", - "\n", - "---\n", - "\n", - "```\n", - "var admin2 = ee.FeatureCollection(\"FAO/GAUL_SIMPLIFIED_500m/2015/level2\");\n", - "\n", - "var karnataka = admin2.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))\n", - "\n", - "var visParams = {color: 'red'}\n", - "Map.centerObject(karnataka)\n", - "Map.addLayer(karnataka, visParams, 'Karnataka Districts')\n", - "```\n", - "---" - ] - } - ], - "metadata": { - "colab": { - "name": "02_automatic_conversion_of_scripts.ipynb", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "WD-QeVYP2iMT" + }, + "source": [ + "[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python.\n", + "\n", + "It comes with a function that can help you translate your javascript earth engine code to Python automatically.\n", + "\n", + "The `geemap` package is pre-installed in Colab." + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "apXfk7X6Uyz2" + }, + "outputs": [], + "source": [ + "import geemap\n", + "import ee" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CpVwpjkjIAJQ" + }, + "source": [ + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gjRJhBKF2iLf" + }, + "outputs": [], + "source": [ + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "37jsLQJiZQ3A" + }, + "source": [ + "#### Automatic Conversion using GUI" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AEr4OXZuVOp0" + }, + "source": [ + "`geemap` comes with a user interface that can be used to interactively do code conversion. Let's try to convert the following Javascript code to Python.\n", + "\n", + "```\n", + "var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]);\n", + "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", + "\n", + "var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};\n", + "\n", + "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", + " .filter(ee.Filter.date('2019-01-01', '2020-01-01'))\n", + " .filter(ee.Filter.bounds(geometry));\n", + " \n", + "var medianComposite = filtered.median();\n", + "\n", + "Map.centerObject(geometry, 10);\n", + "Map.addLayer(medianComposite, rgbVis, 'Median Composite');\n", + "```\n", + "\n", + "Run the cell below to load the map widget. Once the map widget loads, click the *Toolbar* icon in the top-right corner and select the *Convert Earth Engine Javascript to Python* tool. Paste your Javascript code and click *Convert*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "tmTgTEA4VaY1" + }, + "outputs": [], + "source": [ + "m = geemap.Map(width=800)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "kGob1XI3aXve" + }, + "outputs": [], + "source": [ + "geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241])\n", + "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", + "\n", + "rgbVis = {'min': 0.0, 'max': 3000, 'bands': ['B4', 'B3', 'B2']}\n", + "\n", + "filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", + " .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", + " .filter(ee.Filter.bounds(geometry))\n", + "\n", + "medianComposite = filtered.median()\n", + "\n", + "m.centerObject(geometry, 10)\n", + "m.addLayer(medianComposite, rgbVis, 'Median Composite')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AMnk0ZXUXNNL" + }, + "source": [ + "You will see the auto-converted code displayed. Copy and paste it into a new cell and run it. Your code will be run using the GEE Python API. If your code loads any layers, they will be loadded on the map widget. To display it, open a new code cell and just type `m` to display the widget.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "OeHqXTRRYuui" + }, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Yd1eFlklYvr-" + }, + "source": [ + "> Note The auto-conversion is almost perfect and works flawlessly on most GEE code. One place it misses is during the conversion of function arguments specified as a dicitonary. You will need to prefix the resulting code with `**` to specify them as `**kwargs`. For example, the `geemap` converter produces code such as below.\n", + " ```\n", + " stats = image.reduceRegion({\n", + " 'reducer': ee.Reducer.mean(),\n", + " 'geometry': geometry,\n", + " 'scale': 10,\n", + " 'maxPixels': 1e10\n", + " })\n", + " ```\n", + "To make this valid GEE Python API code - prefix the argument dictionary with `**`.\n", + " ```\n", + " stats = image.reduceRegion(**{\n", + " 'reducer': ee.Reducer.mean(),\n", + " 'geometry': geometry,\n", + " 'scale': 10,\n", + " 'maxPixels': 1e10\n", + " })\n", + " ```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qfQyzIgpZN1v" + }, + "source": [ + "#### Automatic Conversion using Code" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vDE9fRr3KqIK" + }, + "source": [ + "`geemap` offers a function `js_snippet_to_py()` that can be used to perform the conversion using code. This is useful for batch conversions. To use this, we first create a string with the javascript code." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "nxPPLtLI2iMa" + }, + "outputs": [], + "source": [ + "javascript_code = \"\"\"\n", + "var geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766]);\n", + "Map.centerObject(geometry, 12)\n", + "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", + "var rgbVis = {\n", + " min: 0.0,\n", + " max: 3000,\n", + " bands: ['B4', 'B3', 'B2'],\n", + "};\n", + "\n", + "// Write a function for Cloud masking\n", + "function maskS2clouds(image) {\n", + " var qa = image.select('QA60')\n", + " var cloudBitMask = 1 << 10;\n", + " var cirrusBitMask = 1 << 11;\n", + " var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(\n", + " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", + " return image.updateMask(mask)\n", + " .select(\"B.*\")\n", + " .copyProperties(image, [\"system:time_start\"])\n", + "}\n", + "\n", + "var filtered = s2\n", + " .filter(ee.Filter.date('2019-01-01', '2019-12-31'))\n", + " .filter(ee.Filter.bounds(geometry))\n", + " .map(maskS2clouds)\n", + "\n", + "\n", + "// Write a function that computes NDVI for an image and adds it as a band\n", + "function addNDVI(image) {\n", + " var ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi');\n", + " return image.addBands(ndvi);\n", + "}\n", + "\n", + "var withNdvi = filtered.map(addNDVI);\n", + "\n", + "var composite = withNdvi.median()\n", + "palette = [\n", + " 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',\n", + " '74A901', '66A000', '529400', '3E8601', '207401', '056201',\n", + " '004C00', '023B01', '012E01', '011D01', '011301'];\n", + "\n", + "ndviVis = {min:0, max:0.5, palette: palette }\n", + "Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')\n", + "\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "zYsztHh42iMf" + }, + "outputs": [], + "source": [ + "lines = geemap.js_snippet_to_py(\n", + " javascript_code, add_new_cell=False,\n", + " import_ee=True, import_geemap=True, show_map=True)\n", + "for line in lines:\n", + " print(line.rstrip())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DMGdvTv3KqIM" + }, + "source": [ + "The automatic conversion works great. Review it and paste it to the cell below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "OnrJ0KZEKqIN" + }, + "outputs": [], + "source": [ + "import ee\n", + "import geemap\n", + "m = geemap.Map()\n", + "\n", + "geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])\n", + "m.centerObject(geometry, 12)\n", + "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", + "rgbVis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "# Write a function for Cloud masking\n", + "def maskS2clouds(image):\n", + " qa = image.select('QA60')\n", + " cloudBitMask = 1 << 10\n", + " cirrusBitMask = 1 << 11\n", + " mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(\n", + " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", + " return image.updateMask(mask) \\\n", + " .select(\"B.*\") \\\n", + " .copyProperties(image, [\"system:time_start\"])\n", + "\n", + "filtered = s2 \\\n", + " .filter(ee.Filter.date('2019-01-01', '2019-12-31')) \\\n", + " .filter(ee.Filter.bounds(geometry)) \\\n", + " .map(maskS2clouds)\n", + "\n", + "# Write a function that computes NDVI for an image and adds it as a band\n", + "def addNDVI(image):\n", + " ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')\n", + " return image.addBands(ndvi)\n", + "\n", + "withNdvi = filtered.map(addNDVI)\n", + "\n", + "composite = withNdvi.median()\n", + "palette = [\n", + " 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',\n", + " '74A901', '66A000', '529400', '3E8601', '207401', '056201',\n", + " '004C00', '023B01', '012E01', '011D01', '011301']\n", + "\n", + "ndviVis = {'min':0, 'max':0.5, 'palette': palette }\n", + "m.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')\n", + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "SH4cW4iZKqIN" + }, + "source": [ + "### Exercise\n", + "\n", + "Take the Javascript code snippet below and use `geemap` to automatically convert it to Python.\n", + "\n", + "---\n", + "\n", + "```\n", + "var admin2 = ee.FeatureCollection(\"FAO/GAUL_SIMPLIFIED_500m/2015/level2\");\n", + "\n", + "var karnataka = admin2.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))\n", + "\n", + "var visParams = {color: 'red'}\n", + "Map.centerObject(karnataka)\n", + "Map.addLayer(karnataka, visParams, 'Karnataka Districts')\n", + "```\n", + "---" + ] + } + ], + "metadata": { + "colab": { + "name": "02_automatic_conversion_of_scripts.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/code/end_to_end_gee/03_export_a_collection.ipynb b/code/end_to_end_gee/03_export_a_collection.ipynb index 6177d8b3..cb09a171 100644 --- a/code/end_to_end_gee/03_export_a_collection.ipynb +++ b/code/end_to_end_gee/03_export_a_collection.ipynb @@ -1,303 +1,303 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "cUfEWS_3PWZr" - }, - "source": [ - "One of the most commonly asked questions by Earth Engine users is - *How do I download all images in a collection*? The Earth Engine Python API comes with a `ee.batch` module that allows you to launch batch exports and manage tasks. The recommended way to do batch exports like this is to use the Python API's `ee.batch.Export` functions and use a Python for-loop to iterate and export each image. The `ee.batch` module also gives you ability to control *Tasks* - allowing you to automate exports.\n", - "\n", - "> You can also export images in a collection using Javascript API in the Code Editor but this requires you to manually start the tasks for each image. This approach is fine for small number of images. You can check out the [recommended script](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3ASupplement%2FImage_Collections%2FExporting_ImageCollections)." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "CpVwpjkjIAJQ" - }, - "source": [ - "#### Initialization\n", - "\n", - "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "JuN5rEoyjmjK" - }, - "outputs": [], - "source": [ - "import ee" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "gjRJhBKF2iLf" - }, - "outputs": [], - "source": [ - "cloud_project = 'spatialthoughts'\n", - "\n", - "try:\n", - " ee.Initialize(project=cloud_project)\n", - "except:\n", - " ee.Authenticate()\n", - " ee.Initialize(project=cloud_project)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "mW0ljMgeg72n" - }, - "source": [ - "#### Create a Collection" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "S60c2-FOjx0h" - }, - "outputs": [], - "source": [ - "geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])\n", - "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", - "rgbVis = {\n", - " 'min': 0.0,\n", - " 'max': 3000,\n", - " 'bands': ['B4', 'B3', 'B2'],\n", - "}\n", - "\n", - "# Write a function for Cloud masking\n", - "def maskS2clouds(image):\n", - " qa = image.select('QA60')\n", - " cloudBitMask = 1 << 10\n", - " cirrusBitMask = 1 << 11\n", - " mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(\n", - " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", - " return image.updateMask(mask) \\\n", - " .select(\"B.*\") \\\n", - " .copyProperties(image, [\"system:time_start\"])\n", - "\n", - "filtered = s2 \\\n", - " .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", - " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", - " .filter(ee.Filter.bounds(geometry)) \\\n", - " .map(maskS2clouds)\n", - "\n", - "# Write a function that computes NDVI for an image and adds it as a band\n", - "def addNDVI(image):\n", - " ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')\n", - " return image.addBands(ndvi)\n", - "\n", - "withNdvi = filtered.map(addNDVI)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "s-zNDMS9g72r" - }, - "source": [ - "#### Export All Images\n", - "\n", - "Exports are done via the ``ee.batch`` module. This module allows you to automatically start an export - making it suitable for batch exports." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "STvfd9ABg72s" - }, - "outputs": [], - "source": [ - "image_ids = withNdvi.aggregate_array('system:index').getInfo()\n", - "print('Total images: ', len(image_ids))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "CoXn1_hgoj81" - }, - "outputs": [], - "source": [ - "# Export with 100m resolution for this demo\n", - "for i, image_id in enumerate(image_ids):\n", - " image = ee.Image(withNdvi.filter(ee.Filter.eq('system:index', image_id)).first())\n", - " task = ee.batch.Export.image.toDrive(**{\n", - " 'image': image.select('ndvi'),\n", - " 'description': 'Image Export {}'.format(i+1),\n", - " 'fileNamePrefix': image_id,\n", - " 'folder':'earthengine',\n", - " 'scale': 100,\n", - " 'region': image.geometry(),\n", - " 'maxPixels': 1e10\n", - " })\n", - " task.start()\n", - " print('Started Task: ', i+1)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "J8BtAZftg720" - }, - "source": [ - "#### Manage Running/Waiting Tasks\n", - "\n", - "You can manage tasks as well. Get a list of tasks and get state information on them" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "AhNgXPb1XGBX" - }, - "outputs": [], - "source": [ - "tasks = ee.batch.Task.list()\n", - "for task in tasks:\n", - " task_id = task.status()['id']\n", - " task_state = task.status()['state']\n", - " print(task_id, task_state)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Y4kf_z5Wg723" - }, - "source": [ - "You can cancel tasks as well" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-u2_GpPog724" - }, - "outputs": [], - "source": [ - "tasks = ee.batch.Task.list()\n", - "for task in tasks:\n", - " task_id = task.status()['id']\n", - " task_state = task.status()['state']\n", - " if task_state == 'RUNNING' or task_state == 'READY':\n", - " task.cancel()\n", - " print('Task {} canceled'.format(task_id))\n", - " else:\n", - " print('Task {} state is {}'.format(task_id, task_state))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nujfioGtPWZ2" - }, - "source": [ - "### Exercise\n", - "\n", - "The code below uses the TerraClimate data and creates an ImageCollection with 12 monthly images of maximum temperature. It also extract the geometry for Australia from the LSIB collection. Add the code to start an export task for each image in the collection for australia.\n", - "\n", - "- **Hint1**: TerraClimate images have a scale of 4638.3m\n", - "- **Hint2**: You need to export the image contained in the clippedImage variable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "27Bwko2sPWZ2" - }, - "outputs": [], - "source": [ - "import ee\n", - "\n", - "lsib = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')\n", - "australia = lsib.filter(ee.Filter.eq('country_na', 'Australia'))\n", - "geometry = australia.geometry()\n", - "\n", - "terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')\n", - "tmax = terraclimate.select('tmmx')\n", - "\n", - "def scale(image):\n", - " return image.multiply(0.1) \\\n", - " .copyProperties(image,['system:time_start'])\n", - "\n", - "tmaxScaled = tmax.map(scale)\n", - "\n", - "filtered = tmaxScaled \\\n", - " .filter(ee.Filter.date('2020-01-01', '2021-01-01')) \\\n", - " .filter(ee.Filter.bounds(geometry))\n", - "\n", - "image_ids = filtered.aggregate_array('system:index').getInfo()\n", - "print('Total images: ', len(image_ids))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fwp4iHF6PWZ2" - }, - "source": [ - "Replace the comments with your code." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "mbR6LaBDPWZ2" - }, - "outputs": [], - "source": [ - "for i, image_id in enumerate(image_ids):\n", - " exportImage = ee.Image(filtered.filter(ee.Filter.eq('system:index', image_id)).first())\n", - " # Clip the image to the region geometry\n", - " clippedImage = exportImage.clip(geometry)\n", - "\n", - " ## Create the export task using ee.batch.Export.image.toDrive()\n", - "\n", - " ## Start the task" - ] - } - ], - "metadata": { - "colab": { - "name": "03_export_a_collection.ipynb", - "provenance": [], - "toc_visible": true - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "cUfEWS_3PWZr" + }, + "source": [ + "One of the most commonly asked questions by Earth Engine users is - *How do I download all images in a collection*? The Earth Engine Python API comes with a `ee.batch` module that allows you to launch batch exports and manage tasks. The recommended way to do batch exports like this is to use the Python API's `ee.batch.Export` functions and use a Python for-loop to iterate and export each image. The `ee.batch` module also gives you ability to control *Tasks* - allowing you to automate exports.\n", + "\n", + "> You can also export images in a collection using Javascript API in the Code Editor but this requires you to manually start the tasks for each image. This approach is fine for small number of images. You can check out the [recommended script](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3ASupplement%2FImage_Collections%2FExporting_ImageCollections)." + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "markdown", + "metadata": { + "id": "CpVwpjkjIAJQ" + }, + "source": [ + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "JuN5rEoyjmjK" + }, + "outputs": [], + "source": [ + "import ee" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gjRJhBKF2iLf" + }, + "outputs": [], + "source": [ + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mW0ljMgeg72n" + }, + "source": [ + "#### Create a Collection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "S60c2-FOjx0h" + }, + "outputs": [], + "source": [ + "geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])\n", + "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", + "rgbVis = {\n", + " 'min': 0.0,\n", + " 'max': 3000,\n", + " 'bands': ['B4', 'B3', 'B2'],\n", + "}\n", + "\n", + "# Write a function for Cloud masking\n", + "def maskS2clouds(image):\n", + " qa = image.select('QA60')\n", + " cloudBitMask = 1 << 10\n", + " cirrusBitMask = 1 << 11\n", + " mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(\n", + " qa.bitwiseAnd(cirrusBitMask).eq(0))\n", + " return image.updateMask(mask) \\\n", + " .select(\"B.*\") \\\n", + " .copyProperties(image, [\"system:time_start\"])\n", + "\n", + "filtered = s2 \\\n", + " .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", + " .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", + " .filter(ee.Filter.bounds(geometry)) \\\n", + " .map(maskS2clouds)\n", + "\n", + "# Write a function that computes NDVI for an image and adds it as a band\n", + "def addNDVI(image):\n", + " ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')\n", + " return image.addBands(ndvi)\n", + "\n", + "withNdvi = filtered.map(addNDVI)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "s-zNDMS9g72r" + }, + "source": [ + "#### Export All Images\n", + "\n", + "Exports are done via the ``ee.batch`` module. This module allows you to automatically start an export - making it suitable for batch exports." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "STvfd9ABg72s" + }, + "outputs": [], + "source": [ + "image_ids = withNdvi.aggregate_array('system:index').getInfo()\n", + "print('Total images: ', len(image_ids))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "CoXn1_hgoj81" + }, + "outputs": [], + "source": [ + "# Export with 100m resolution for this demo\n", + "for i, image_id in enumerate(image_ids):\n", + " image = ee.Image(withNdvi.filter(ee.Filter.eq('system:index', image_id)).first())\n", + " task = ee.batch.Export.image.toDrive(**{\n", + " 'image': image.select('ndvi'),\n", + " 'description': 'Image Export {}'.format(i+1),\n", + " 'fileNamePrefix': image_id,\n", + " 'folder':'earthengine',\n", + " 'scale': 100,\n", + " 'region': image.geometry(),\n", + " 'maxPixels': 1e10\n", + " })\n", + " task.start()\n", + " print('Started Task: ', i+1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "J8BtAZftg720" + }, + "source": [ + "#### Manage Running/Waiting Tasks\n", + "\n", + "You can manage tasks as well. Get a list of tasks and get state information on them" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "AhNgXPb1XGBX" + }, + "outputs": [], + "source": [ + "tasks = ee.batch.Task.list()\n", + "for task in tasks:\n", + " task_id = task.status()['id']\n", + " task_state = task.status()['state']\n", + " print(task_id, task_state)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Y4kf_z5Wg723" + }, + "source": [ + "You can cancel tasks as well" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "-u2_GpPog724" + }, + "outputs": [], + "source": [ + "tasks = ee.batch.Task.list()\n", + "for task in tasks:\n", + " task_id = task.status()['id']\n", + " task_state = task.status()['state']\n", + " if task_state == 'RUNNING' or task_state == 'READY':\n", + " task.cancel()\n", + " print('Task {} canceled'.format(task_id))\n", + " else:\n", + " print('Task {} state is {}'.format(task_id, task_state))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nujfioGtPWZ2" + }, + "source": [ + "### Exercise\n", + "\n", + "The code below uses the TerraClimate data and creates an ImageCollection with 12 monthly images of maximum temperature. It also extract the geometry for Australia from the LSIB collection. Add the code to start an export task for each image in the collection for australia.\n", + "\n", + "- **Hint1**: TerraClimate images have a scale of 4638.3m\n", + "- **Hint2**: You need to export the image contained in the clippedImage variable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "27Bwko2sPWZ2" + }, + "outputs": [], + "source": [ + "import ee\n", + "\n", + "lsib = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')\n", + "australia = lsib.filter(ee.Filter.eq('country_na', 'Australia'))\n", + "geometry = australia.geometry()\n", + "\n", + "terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')\n", + "tmax = terraclimate.select('tmmx')\n", + "\n", + "def scale(image):\n", + " return image.multiply(0.1) \\\n", + " .copyProperties(image,['system:time_start'])\n", + "\n", + "tmaxScaled = tmax.map(scale)\n", + "\n", + "filtered = tmaxScaled \\\n", + " .filter(ee.Filter.date('2020-01-01', '2021-01-01')) \\\n", + " .filter(ee.Filter.bounds(geometry))\n", + "\n", + "image_ids = filtered.aggregate_array('system:index').getInfo()\n", + "print('Total images: ', len(image_ids))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fwp4iHF6PWZ2" + }, + "source": [ + "Replace the comments with your code." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "mbR6LaBDPWZ2" + }, + "outputs": [], + "source": [ + "for i, image_id in enumerate(image_ids):\n", + " exportImage = ee.Image(filtered.filter(ee.Filter.eq('system:index', image_id)).first())\n", + " # Clip the image to the region geometry\n", + " clippedImage = exportImage.clip(geometry)\n", + "\n", + " ## Create the export task using ee.batch.Export.image.toDrive()\n", + "\n", + " ## Start the task" + ] + } + ], + "metadata": { + "colab": { + "name": "03_export_a_collection.ipynb", + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/code/end_to_end_gee/04_creating_charts.ipynb b/code/end_to_end_gee/04_creating_charts.ipynb index 5731af9b..36a320d2 100644 --- a/code/end_to_end_gee/04_creating_charts.ipynb +++ b/code/end_to_end_gee/04_creating_charts.ipynb @@ -1,360 +1,360 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "N4ioBJAxPzIC" - }, - "source": [ - "The Google Earth Engine Python API does not come with a charting module. But you can use third-party modules to create interactive charts. You may also convert the Earth Engine objects to a Pandas dataframe and plot it using Python libraries like Matplotlib\n", - "\n", - "This notebook shows how to use the `geemap` package to create a Time-Series Chart from a ImageCollection.\n", - "\n", - "References:\n", - "\n", - "- geemap [Chart module](https://geemap.org/chart/)\n", - "- geemap [Example notebook](https://geemap.org/notebooks/63_charts/)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "CpVwpjkjIAJQ" - }, - "source": [ - "#### Initialization\n", - "\n", - "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." - ] - }, - { - "cell_type": "code", - "source": [ - "import geemap\n", - "import ee" - ], - "metadata": { - "id": "apXfk7X6Uyz2" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "gjRJhBKF2iLf" - }, - "outputs": [], - "source": [ - "cloud_project = 'spatialthoughts'\n", - "\n", - "try:\n", - " ee.Initialize(project=cloud_project)\n", - "except:\n", - " ee.Authenticate()\n", - " ee.Initialize(project=cloud_project)" - ] - }, - { - "cell_type": "markdown", - "source": [ - "#### Load and Process the Data" - ], - "metadata": { - "id": "PnlIxXyoeKaf" - } - }, - { - "cell_type": "markdown", - "metadata": { - "id": "XueIYfXSPzII" - }, - "source": [ - "Load the TerraClimate collection and select the 'tmmx' band." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "IPn2h8uA6kPg" - }, - "outputs": [], - "source": [ - "terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')\n", - "tmax = terraclimate.select('tmmx')" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ZflvwpS4PzIJ" - }, - "source": [ - "Define a point location for the chart." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "EtfX6A2fPzIJ" - }, - "outputs": [], - "source": [ - "geometry = ee.Geometry.Point([77.57738128916243, 12.964758918835752])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ZpL2feqtPzIK" - }, - "source": [ - "Scale the band values so they are in Degree Celcius." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "g2iFLh6D7Jed" - }, - "outputs": [], - "source": [ - "def scale_image(image):\n", - " return ee.Image(image).multiply(0.1)\\\n", - " .copyProperties(image, ['system:time_start'])\n", - "\n", - "tmaxScaled = tmax.map(scale_image)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nmSBepxy7p_N" - }, - "source": [ - "Filter the collection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "1rY5FsgZ79Kd" - }, - "outputs": [], - "source": [ - "filtered = tmaxScaled.filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", - " .filter(ee.Filter.bounds(geometry))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Q6Lip5RnPzIL" - }, - "source": [ - "To chart an image series in Python, we must first extract the values from each image and create a FeatureCollection." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "m2UYiMXNDrNr" - }, - "outputs": [], - "source": [ - "def extract_data(image):\n", - " stats = image.reduceRegion(**{\n", - " 'reducer':ee.Reducer.mean(),\n", - " 'geometry':geometry,\n", - " 'scale':5000\n", - " })\n", - " properties = {\n", - " 'month': image.get('system:index'),\n", - " 'tmmx': stats.get('tmmx')\n", - " }\n", - " return ee.Feature(None, properties)\n", - "\n", - "data = ee.FeatureCollection(filtered.map(extract_data))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "JLuHymf4PzIL" - }, - "outputs": [], - "source": [ - "print(data.first().getInfo())" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "TVfq6ObhPzIL" - }, - "source": [ - "#### Create an Interactive Chart using geemap" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "4dtk1ix1PzIM" - }, - "outputs": [], - "source": [ - "from geemap import chart" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "C31rXB7JPzIM" - }, - "outputs": [], - "source": [ - "options = {\n", - " 'title': 'Max Monthly Temperature at Bangalore',\n", - " 'legend_location': 'top-right',\n", - " 'height': '500px',\n", - " 'ylabel': 'Temperature (C)',\n", - " 'xlabel': 'Date',\n", - " 'colors': ['blue']\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "543g2jdBJUCs" - }, - "outputs": [], - "source": [ - "chart.feature_byFeature(data, 'month', ['tmmx'], **options)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0EbOPBTCPzIM" - }, - "source": [ - "#### Create a chart using Matplotlib\n", - "\n", - "We can convert a FeatureCollection to a DataFrame using `geemap` helper function `ee_to_pandas`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "mnYFnRaSPzIM" - }, - "outputs": [], - "source": [ - "import geemap\n", - "df = geemap.ee_to_pandas(data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "htS7yEhZPzIN" - }, - "outputs": [], - "source": [ - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "dbtjbuUPPzIN" - }, - "source": [ - "Now we have a regular Pandas dataframe that can be plotted with `matplotlib`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "TEKYYnroPzIN" - }, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "4nNroiqTPzIN" - }, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "fig.set_size_inches(20,10)\n", - "\n", - "\n", - "df.plot(ax=ax,\n", - " title='Max Monthly Temperature at Bangalore',\n", - " x='month',\n", - " ylabel='Temperature (C)',\n", - " kind='line')\n", - "plt.tight_layout()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "cfYVUaEKPzIN" - }, - "source": [ - "### Exercise\n", - "\n", - "Customize the above chart by plotting it as a Line Chart in red color.\n", - "\n", - "- **Hint1**: Use `kind='line'` along with a `color` option." - ] - } - ], - "metadata": { - "colab": { - "name": "04_creating_charts.ipynb", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.13" - } + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "N4ioBJAxPzIC" + }, + "source": [ + "The Google Earth Engine Python API does not come with a charting module. But you can use third-party modules to create interactive charts. You may also convert the Earth Engine objects to a Pandas dataframe and plot it using Python libraries like Matplotlib\n", + "\n", + "This notebook shows how to use the `geemap` package to create a Time-Series Chart from a ImageCollection.\n", + "\n", + "References:\n", + "\n", + "- geemap [Chart module](https://geemap.org/chart/)\n", + "- geemap [Example notebook](https://geemap.org/notebooks/63_charts/)\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 -} \ No newline at end of file + { + "cell_type": "markdown", + "metadata": { + "id": "CpVwpjkjIAJQ" + }, + "source": [ + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "apXfk7X6Uyz2" + }, + "outputs": [], + "source": [ + "import geemap\n", + "import ee" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gjRJhBKF2iLf" + }, + "outputs": [], + "source": [ + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PnlIxXyoeKaf" + }, + "source": [ + "#### Load and Process the Data" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XueIYfXSPzII" + }, + "source": [ + "Load the TerraClimate collection and select the 'tmmx' band." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "IPn2h8uA6kPg" + }, + "outputs": [], + "source": [ + "terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')\n", + "tmax = terraclimate.select('tmmx')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZflvwpS4PzIJ" + }, + "source": [ + "Define a point location for the chart." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "EtfX6A2fPzIJ" + }, + "outputs": [], + "source": [ + "geometry = ee.Geometry.Point([77.57738128916243, 12.964758918835752])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZpL2feqtPzIK" + }, + "source": [ + "Scale the band values so they are in Degree Celcius." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "g2iFLh6D7Jed" + }, + "outputs": [], + "source": [ + "def scale_image(image):\n", + " return ee.Image(image).multiply(0.1)\\\n", + " .copyProperties(image, ['system:time_start'])\n", + "\n", + "tmaxScaled = tmax.map(scale_image)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nmSBepxy7p_N" + }, + "source": [ + "Filter the collection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "1rY5FsgZ79Kd" + }, + "outputs": [], + "source": [ + "filtered = tmaxScaled.filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", + " .filter(ee.Filter.bounds(geometry))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Q6Lip5RnPzIL" + }, + "source": [ + "To chart an image series in Python, we must first extract the values from each image and create a FeatureCollection." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "m2UYiMXNDrNr" + }, + "outputs": [], + "source": [ + "def extract_data(image):\n", + " stats = image.reduceRegion(**{\n", + " 'reducer':ee.Reducer.mean(),\n", + " 'geometry':geometry,\n", + " 'scale':5000\n", + " })\n", + " properties = {\n", + " 'month': image.get('system:index'),\n", + " 'tmmx': stats.get('tmmx')\n", + " }\n", + " return ee.Feature(None, properties)\n", + "\n", + "data = ee.FeatureCollection(filtered.map(extract_data))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "JLuHymf4PzIL" + }, + "outputs": [], + "source": [ + "print(data.first().getInfo())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TVfq6ObhPzIL" + }, + "source": [ + "#### Create an Interactive Chart using geemap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "4dtk1ix1PzIM" + }, + "outputs": [], + "source": [ + "from geemap import chart" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "C31rXB7JPzIM" + }, + "outputs": [], + "source": [ + "options = {\n", + " 'title': 'Max Monthly Temperature at Bangalore',\n", + " 'legend_location': 'top-right',\n", + " 'height': '500px',\n", + " 'ylabel': 'Temperature (C)',\n", + " 'xlabel': 'Date',\n", + " 'colors': ['blue']\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "543g2jdBJUCs" + }, + "outputs": [], + "source": [ + "chart.feature_byFeature(data, 'month', ['tmmx'], **options)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0EbOPBTCPzIM" + }, + "source": [ + "#### Create a chart using Matplotlib\n", + "\n", + "We can convert a FeatureCollection to a DataFrame using `geemap` helper function `ee_to_pandas`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "mnYFnRaSPzIM" + }, + "outputs": [], + "source": [ + "import geemap\n", + "df = geemap.ee_to_pandas(data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "htS7yEhZPzIN" + }, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dbtjbuUPPzIN" + }, + "source": [ + "Now we have a regular Pandas dataframe that can be plotted with `matplotlib`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "TEKYYnroPzIN" + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "4nNroiqTPzIN" + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "fig.set_size_inches(20,10)\n", + "\n", + "\n", + "df.plot(ax=ax,\n", + " title='Max Monthly Temperature at Bangalore',\n", + " x='month',\n", + " ylabel='Temperature (C)',\n", + " kind='line')\n", + "plt.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cfYVUaEKPzIN" + }, + "source": [ + "### Exercise\n", + "\n", + "Customize the above chart by plotting it as a Line Chart in red color.\n", + "\n", + "- **Hint1**: Use `kind='line'` along with a `color` option." + ] + } + ], + "metadata": { + "colab": { + "name": "04_creating_charts.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/code/end_to_end_gee/01_python_api_syntax.ipynb b/docs/code/end_to_end_gee/01_python_api_syntax.ipynb index 3336d1e3..5172d5bd 100644 --- a/docs/code/end_to_end_gee/01_python_api_syntax.ipynb +++ b/docs/code/end_to_end_gee/01_python_api_syntax.ipynb @@ -19,7 +19,9 @@ "source": [ "#### Initialization\n", "\n", - "First of all, you need to run the following cells to initialize the API and authorize your account. You will be prompted to sign-in to the account and allow access to *View and Manage your Earth Engine data*. Once you approve, you will get an a verification code that needs to be entered at the prompt. This step needs to be done just once per session." + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/).\n", + "\n", + "You will be prompted to allow the notebook to access your Google credentials to sign-in to the account and allow access to *Google Drive and Google Cloud data*. Once you approve, it will proceed to initialize the Earth Engine API. This step needs to be done just once per session." ] }, { @@ -41,18 +43,13 @@ }, "outputs": [], "source": [ - "ee.Authenticate()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "KwN_Ti_YIAJS" - }, - "outputs": [], - "source": [ - "ee.Initialize()" + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)\n" ] }, { diff --git a/docs/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb b/docs/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb index ec295056..335a567b 100644 --- a/docs/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb +++ b/docs/code/end_to_end_gee/02_automatic_conversion_of_scripts.ipynb @@ -6,30 +6,178 @@ "id": "WD-QeVYP2iMT" }, "source": [ - "[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python. \n", + "[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python.\n", "\n", "It comes with a function that can help you translate your javascript earth engine code to Python automatically.\n", "\n", - "Google Colab doesn't come pre-installed with the package, so we install it via pip." + "The `geemap` package is pre-installed in Colab." ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "id": "nlQ8X57t2iMW" + "id": "apXfk7X6Uyz2" }, "outputs": [], "source": [ + "import geemap\n", + "import ee" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CpVwpjkjIAJQ" + }, + "source": [ + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gjRJhBKF2iLf" + }, + "outputs": [], + "source": [ + "cloud_project = 'spatialthoughts'\n", + "\n", "try:\n", - " import geemap\n", - "except ModuleNotFoundError:\n", - " if 'google.colab' in str(get_ipython()):\n", - " print('geemap not found, installing via pip in Google Colab...')\n", - " !pip install geemap --quiet\n", - " import geemap\n", - " else:\n", - " print('geemap not found, please install via conda in your environment')" + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "37jsLQJiZQ3A" + }, + "source": [ + "#### Automatic Conversion using GUI" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AEr4OXZuVOp0" + }, + "source": [ + "`geemap` comes with a user interface that can be used to interactively do code conversion. Let's try to convert the following Javascript code to Python.\n", + "\n", + "```\n", + "var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]);\n", + "var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');\n", + "\n", + "var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};\n", + "\n", + "var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))\n", + " .filter(ee.Filter.date('2019-01-01', '2020-01-01'))\n", + " .filter(ee.Filter.bounds(geometry));\n", + " \n", + "var medianComposite = filtered.median();\n", + "\n", + "Map.centerObject(geometry, 10);\n", + "Map.addLayer(medianComposite, rgbVis, 'Median Composite');\n", + "```\n", + "\n", + "Run the cell below to load the map widget. Once the map widget loads, click the *Toolbar* icon in the top-right corner and select the *Convert Earth Engine Javascript to Python* tool. Paste your Javascript code and click *Convert*." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "tmTgTEA4VaY1" + }, + "outputs": [], + "source": [ + "m = geemap.Map(width=800)\n", + "m" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "kGob1XI3aXve" + }, + "outputs": [], + "source": [ + "geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241])\n", + "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", + "\n", + "rgbVis = {'min': 0.0, 'max': 3000, 'bands': ['B4', 'B3', 'B2']}\n", + "\n", + "filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \\\n", + " .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \\\n", + " .filter(ee.Filter.bounds(geometry))\n", + "\n", + "medianComposite = filtered.median()\n", + "\n", + "m.centerObject(geometry, 10)\n", + "m.addLayer(medianComposite, rgbVis, 'Median Composite')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AMnk0ZXUXNNL" + }, + "source": [ + "You will see the auto-converted code displayed. Copy and paste it into a new cell and run it. Your code will be run using the GEE Python API. If your code loads any layers, they will be loadded on the map widget. To display it, open a new code cell and just type `m` to display the widget.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "OeHqXTRRYuui" + }, + "outputs": [], + "source": [ + "m" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Yd1eFlklYvr-" + }, + "source": [ + "> Note The auto-conversion is almost perfect and works flawlessly on most GEE code. One place it misses is during the conversion of function arguments specified as a dicitonary. You will need to prefix the resulting code with `**` to specify them as `**kwargs`. For example, the `geemap` converter produces code such as below.\n", + " ```\n", + " stats = image.reduceRegion({\n", + " 'reducer': ee.Reducer.mean(),\n", + " 'geometry': geometry,\n", + " 'scale': 10,\n", + " 'maxPixels': 1e10\n", + " })\n", + " ```\n", + "To make this valid GEE Python API code - prefix the argument dictionary with `**`.\n", + " ```\n", + " stats = image.reduceRegion(**{\n", + " 'reducer': ee.Reducer.mean(),\n", + " 'geometry': geometry,\n", + " 'scale': 10,\n", + " 'maxPixels': 1e10\n", + " })\n", + " ```" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "qfQyzIgpZN1v" + }, + "source": [ + "#### Automatic Conversion using Code" ] }, { @@ -38,7 +186,7 @@ "id": "vDE9fRr3KqIK" }, "source": [ - "The automatic conversion of code is done by calling the `geemap.js_snippet_to_py()` function. We first create a string with the javascript code." + "`geemap` offers a function `js_snippet_to_py()` that can be used to perform the conversion using code. This is useful for batch conversions. To use this, we first create a string with the javascript code." ] }, { @@ -70,12 +218,12 @@ " .select(\"B.*\")\n", " .copyProperties(image, [\"system:time_start\"])\n", "}\n", - " \n", + "\n", "var filtered = s2\n", " .filter(ee.Filter.date('2019-01-01', '2019-12-31'))\n", " .filter(ee.Filter.bounds(geometry))\n", " .map(maskS2clouds)\n", - " \n", + "\n", "\n", "// Write a function that computes NDVI for an image and adds it as a band\n", "function addNDVI(image) {\n", @@ -131,10 +279,10 @@ "source": [ "import ee\n", "import geemap\n", - "Map = geemap.Map()\n", + "m = geemap.Map()\n", "\n", "geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])\n", - "Map.centerObject(geometry, 12)\n", + "m.centerObject(geometry, 12)\n", "s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')\n", "rgbVis = {\n", " 'min': 0.0,\n", @@ -172,8 +320,8 @@ " '004C00', '023B01', '012E01', '011D01', '011301']\n", "\n", "ndviVis = {'min':0, 'max':0.5, 'palette': palette }\n", - "Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')\n", - "Map" + "m.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')\n", + "m" ] }, { diff --git a/docs/code/end_to_end_gee/03_export_a_collection.ipynb b/docs/code/end_to_end_gee/03_export_a_collection.ipynb index e44aa6cc..cb09a171 100644 --- a/docs/code/end_to_end_gee/03_export_a_collection.ipynb +++ b/docs/code/end_to_end_gee/03_export_a_collection.ipynb @@ -12,36 +12,42 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { - "id": "JuN5rEoyjmjK" + "id": "CpVwpjkjIAJQ" }, - "outputs": [], "source": [ - "import ee" + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "id": "Sz-01eMjg72f" + "id": "JuN5rEoyjmjK" }, "outputs": [], "source": [ - "ee.Authenticate()" + "import ee" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "id": "UPsm1_Qxg72j" + "id": "gjRJhBKF2iLf" }, "outputs": [], "source": [ - "ee.Initialize()" + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)" ] }, { diff --git a/docs/code/end_to_end_gee/04_creating_charts.ipynb b/docs/code/end_to_end_gee/04_creating_charts.ipynb index 6d71a5b3..36a320d2 100644 --- a/docs/code/end_to_end_gee/04_creating_charts.ipynb +++ b/docs/code/end_to_end_gee/04_creating_charts.ipynb @@ -17,55 +17,52 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { - "id": "Nth8Bjdr6PgV" + "id": "CpVwpjkjIAJQ" }, - "outputs": [], "source": [ - "import ee" + "#### Initialization\n", + "\n", + "First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "id": "VGhYEF-WPzIH" + "id": "apXfk7X6Uyz2" }, "outputs": [], "source": [ - "try:\n", - " import geemap\n", - "except ModuleNotFoundError:\n", - " if 'google.colab' in str(get_ipython()):\n", - " print('geemap not found, installing via pip in Google Colab...')\n", - " !pip install geemap --quiet\n", - " import geemap\n", - " else:\n", - " print('geemap not found, please install via conda in your environment')" + "import geemap\n", + "import ee" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "id": "pTg1Z9Ox6STq" + "id": "gjRJhBKF2iLf" }, "outputs": [], "source": [ - "ee.Authenticate()" + "cloud_project = 'spatialthoughts'\n", + "\n", + "try:\n", + " ee.Initialize(project=cloud_project)\n", + "except:\n", + " ee.Authenticate()\n", + " ee.Initialize(project=cloud_project)" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": { - "id": "gOOrdeze6WHE" + "id": "PnlIxXyoeKaf" }, - "outputs": [], "source": [ - "ee.Initialize()" + "#### Load and Process the Data" ] }, { @@ -172,7 +169,7 @@ "outputs": [], "source": [ "def extract_data(image):\n", - " stats = image.reduceRegion(**{ \n", + " stats = image.reduceRegion(**{\n", " 'reducer':ee.Reducer.mean(),\n", " 'geometry':geometry,\n", " 'scale':5000\n", @@ -203,7 +200,7 @@ "id": "TVfq6ObhPzIL" }, "source": [ - "### Create an Interactive Chart using geemap" + "#### Create an Interactive Chart using geemap" ] }, { @@ -226,7 +223,7 @@ "outputs": [], "source": [ "options = {\n", - " 'title': 'Max Monthly Temperature at Bangalore', \n", + " 'title': 'Max Monthly Temperature at Bangalore',\n", " 'legend_location': 'top-right',\n", " 'height': '500px',\n", " 'ylabel': 'Temperature (C)',\n", @@ -252,7 +249,7 @@ "id": "0EbOPBTCPzIM" }, "source": [ - "### Create a chart using Matplotlib\n", + "#### Create a chart using Matplotlib\n", "\n", "We can convert a FeatureCollection to a DataFrame using `geemap` helper function `ee_to_pandas`." ] diff --git a/docs/code/end_to_end_gee/download_data.py b/docs/code/end_to_end_gee/download_data.py index 04626ccb..eed0db7c 100644 --- a/docs/code/end_to_end_gee/download_data.py +++ b/docs/code/end_to_end_gee/download_data.py @@ -3,7 +3,13 @@ import csv import os -ee.Initialize() +cloud_project = 'spatialthoughts' + +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) # Get current date and convert to milliseconds start_date = ee.Date.fromYMD(2022, 1, 1) diff --git a/docs/end-to-end-gee-output/01_python_api_syntax.md b/docs/end-to-end-gee-output/01_python_api_syntax.md index f8eeee9f..eef16816 100644 --- a/docs/end-to-end-gee-output/01_python_api_syntax.md +++ b/docs/end-to-end-gee-output/01_python_api_syntax.md @@ -4,7 +4,9 @@ Coming from the programming in Earth Engine through the Code Editor, you will ne #### Initialization -First of all, you need to run the following cells to initialize the API and authorize your account. You will be prompted to sign-in to the account and allow access to *View and Manage your Earth Engine data*. Once you approve, you will get an a verification code that needs to be entered at the prompt. This step needs to be done just once per session. +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). + +You will be prompted to allow the notebook to access your Google credentials to sign-in to the account and allow access to *Google Drive and Google Cloud data*. Once you approve, it will proceed to initialize the Earth Engine API. This step needs to be done just once per session. ```python @@ -13,12 +15,14 @@ import ee ```python -ee.Authenticate() -``` +cloud_project = 'spatialthoughts' +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) -```python -ee.Initialize() ``` #### Variables diff --git a/docs/end-to-end-gee-output/02_automatic_conversion_of_scripts.md b/docs/end-to-end-gee-output/02_automatic_conversion_of_scripts.md index 6037a5d9..8597bfc0 100644 --- a/docs/end-to-end-gee-output/02_automatic_conversion_of_scripts.md +++ b/docs/end-to-end-gee-output/02_automatic_conversion_of_scripts.md @@ -1,23 +1,107 @@ -[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python. +[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python. It comes with a function that can help you translate your javascript earth engine code to Python automatically. -Google Colab doesn't come pre-installed with the package, so we install it via pip. +The `geemap` package is pre-installed in Colab. ```python +import geemap +import ee +``` + +#### Initialization + +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). + + +```python +cloud_project = 'spatialthoughts' + try: - import geemap -except ModuleNotFoundError: - if 'google.colab' in str(get_ipython()): - print('geemap not found, installing via pip in Google Colab...') - !pip install geemap --quiet - import geemap - else: - print('geemap not found, please install via conda in your environment') + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) +``` + +#### Automatic Conversion using GUI + +`geemap` comes with a user interface that can be used to interactively do code conversion. Let's try to convert the following Javascript code to Python. + +``` +var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]); +var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED'); + +var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']}; + +var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) + .filter(ee.Filter.date('2019-01-01', '2020-01-01')) + .filter(ee.Filter.bounds(geometry)); + +var medianComposite = filtered.median(); + +Map.centerObject(geometry, 10); +Map.addLayer(medianComposite, rgbVis, 'Median Composite'); +``` + +Run the cell below to load the map widget. Once the map widget loads, click the *Toolbar* icon in the top-right corner and select the *Convert Earth Engine Javascript to Python* tool. Paste your Javascript code and click *Convert*. + + +```python +m = geemap.Map(width=800) +m ``` -The automatic conversion of code is done by calling the `geemap.js_snippet_to_py()` function. We first create a string with the javascript code. + +```python +geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]) +s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED') + +rgbVis = {'min': 0.0, 'max': 3000, 'bands': ['B4', 'B3', 'B2']} + +filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \ + .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \ + .filter(ee.Filter.bounds(geometry)) + +medianComposite = filtered.median() + +m.centerObject(geometry, 10) +m.addLayer(medianComposite, rgbVis, 'Median Composite') + +``` + +You will see the auto-converted code displayed. Copy and paste it into a new cell and run it. Your code will be run using the GEE Python API. If your code loads any layers, they will be loadded on the map widget. To display it, open a new code cell and just type `m` to display the widget. + + + + +```python +m +``` + +> Note The auto-conversion is almost perfect and works flawlessly on most GEE code. One place it misses is during the conversion of function arguments specified as a dicitonary. You will need to prefix the resulting code with `**` to specify them as `**kwargs`. For example, the `geemap` converter produces code such as below. + ``` + stats = image.reduceRegion({ + 'reducer': ee.Reducer.mean(), + 'geometry': geometry, + 'scale': 10, + 'maxPixels': 1e10 + }) + ``` +To make this valid GEE Python API code - prefix the argument dictionary with `**`. + ``` + stats = image.reduceRegion(**{ + 'reducer': ee.Reducer.mean(), + 'geometry': geometry, + 'scale': 10, + 'maxPixels': 1e10 + }) + ``` + +#### Automatic Conversion using Code + +`geemap` offers a function `js_snippet_to_py()` that can be used to perform the conversion using code. This is useful for batch conversions. To use this, we first create a string with the javascript code. ```python @@ -42,12 +126,12 @@ function maskS2clouds(image) { .select("B.*") .copyProperties(image, ["system:time_start"]) } - + var filtered = s2 .filter(ee.Filter.date('2019-01-01', '2019-12-31')) .filter(ee.Filter.bounds(geometry)) .map(maskS2clouds) - + // Write a function that computes NDVI for an image and adds it as a band function addNDVI(image) { @@ -84,10 +168,10 @@ The automatic conversion works great. Review it and paste it to the cell below. ```python import ee import geemap -Map = geemap.Map() +m = geemap.Map() geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766]) -Map.centerObject(geometry, 12) +m.centerObject(geometry, 12) s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED') rgbVis = { 'min': 0.0, @@ -125,8 +209,8 @@ palette = [ '004C00', '023B01', '012E01', '011D01', '011301'] ndviVis = {'min':0, 'max':0.5, 'palette': palette } -Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite') -Map +m.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite') +m ``` ### Exercise diff --git a/docs/end-to-end-gee-output/03_export_a_collection.md b/docs/end-to-end-gee-output/03_export_a_collection.md index 1efa3c4d..29b92c66 100644 --- a/docs/end-to-end-gee-output/03_export_a_collection.md +++ b/docs/end-to-end-gee-output/03_export_a_collection.md @@ -2,19 +2,24 @@ One of the most commonly asked questions by Earth Engine users is - *How do I do > You can also export images in a collection using Javascript API in the Code Editor but this requires you to manually start the tasks for each image. This approach is fine for small number of images. You can check out the [recommended script](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3ASupplement%2FImage_Collections%2FExporting_ImageCollections). +#### Initialization -```python -import ee -``` +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). ```python -ee.Authenticate() +import ee ``` ```python -ee.Initialize() +cloud_project = 'spatialthoughts' + +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) ``` #### Create a Collection diff --git a/docs/end-to-end-gee-output/04_creating_charts.md b/docs/end-to-end-gee-output/04_creating_charts.md index b69f4ea3..a2a9b46f 100644 --- a/docs/end-to-end-gee-output/04_creating_charts.md +++ b/docs/end-to-end-gee-output/04_creating_charts.md @@ -8,34 +8,29 @@ References: - geemap [Example notebook](https://geemap.org/notebooks/63_charts/) +#### Initialization -```python -import ee -``` +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). ```python -try: - import geemap -except ModuleNotFoundError: - if 'google.colab' in str(get_ipython()): - print('geemap not found, installing via pip in Google Colab...') - !pip install geemap --quiet - import geemap - else: - print('geemap not found, please install via conda in your environment') +import geemap +import ee ``` ```python -ee.Authenticate() -``` - +cloud_project = 'spatialthoughts' -```python -ee.Initialize() +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) ``` +#### Load and Process the Data + Load the TerraClimate collection and select the 'tmmx' band. @@ -75,7 +70,7 @@ To chart an image series in Python, we must first extract the values from each i ```python def extract_data(image): - stats = image.reduceRegion(**{ + stats = image.reduceRegion(**{ 'reducer':ee.Reducer.mean(), 'geometry':geometry, 'scale':5000 @@ -94,7 +89,7 @@ data = ee.FeatureCollection(filtered.map(extract_data)) print(data.first().getInfo()) ``` -### Create an Interactive Chart using geemap +#### Create an Interactive Chart using geemap ```python @@ -104,7 +99,7 @@ from geemap import chart ```python options = { - 'title': 'Max Monthly Temperature at Bangalore', + 'title': 'Max Monthly Temperature at Bangalore', 'legend_location': 'top-right', 'height': '500px', 'ylabel': 'Temperature (C)', @@ -118,7 +113,7 @@ options = { chart.feature_byFeature(data, 'month', ['tmmx'], **options) ``` -### Create a chart using Matplotlib +#### Create a chart using Matplotlib We can convert a FeatureCollection to a DataFrame using `geemap` helper function `ee_to_pandas`. diff --git a/docs/end-to-end-gee.html b/docs/end-to-end-gee.html index 78ea73f1..1fb2af16 100644 --- a/docs/end-to-end-gee.html +++ b/docs/end-to-end-gee.html @@ -599,12 +599,6 @@

Ujaval Gandhi

  • 04. Creating Charts in Python
  • 05. @@ -4553,17 +4547,25 @@

    01. Python API Syntax

    Initialization

    First of all, you need to run the following cells to initialize the -API and authorize your account. You will be prompted to sign-in to the -account and allow access to View and Manage your Earth Engine -data. Once you approve, you will get an a verification code that -needs to be entered at the prompt. This step needs to be done just once +API and authorize your account. You must have a Google Cloud Project +associated with your GEE account. Replace the cloud_project +with your own project from Google Cloud Console.

    +

    You will be prompted to allow the notebook to access your Google +credentials to sign-in to the account and allow access to Google +Drive and Google Cloud data. Once you approve, it will proceed to +initialize the Earth Engine API. This step needs to be done just once per session.

    import ee
    ee.Authenticate()
    -
    ee.Initialize()
    +class="sourceCode python">cloud_project = 'spatialthoughts' + +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project)

    Variables

    @@ -4575,26 +4577,26 @@

    Variables

    var population = 881549 print(population) -
    city = 'San Fransico'
    -state = 'California'
    -print(city, state)
    -
    -population = 881549
    -print(population)
    +
    city = 'San Fransico'
    +state = 'California'
    +print(city, state)
    +
    +population = 881549
    +print(population)

    Earth Engine Objects

    You can create Earth Engine objects using the ee functions the same way.

    -
    s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    -geometry = ee.Geometry.Polygon([[
    -  [82.60642647743225, 27.16350437805251],
    -  [82.60984897613525, 27.1618529901377],
    -  [82.61088967323303, 27.163695288375266],
    -  [82.60757446289062, 27.16517483230927]
    -]])
    +
    s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    +geometry = ee.Geometry.Polygon([[
    +  [82.60642647743225, 27.16350437805251],
    +  [82.60984897613525, 27.1618529901377],
    +  [82.61088967323303, 27.163695288375266],
    +  [82.60757446289062, 27.16517483230927]
    +]])

    Line Continuation

    @@ -4605,11 +4607,11 @@

    Line Continuation

    var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) .filter(ee.Filter.date('2019-02-01', '2019-03-01')) .filter(ee.Filter.bounds(geometry)); -
    filtered = s2 \
    -    .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \
    -    .filter(ee.Filter.date('2019-02-01', '2019-03-01')) \
    -    .filter(ee.Filter.bounds(geometry))
    +
    filtered = s2 \
    +    .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \
    +    .filter(ee.Filter.date('2019-02-01', '2019-03-01')) \
    +    .filter(ee.Filter.bounds(geometry))

    Functions

    @@ -4638,24 +4640,24 @@

    Functions

    var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi'); return image.addBands(ndvi); } -
    def maskS2clouds(image):
    -  qa = image.select('QA60')
    -  cloudBitMask = 1 << 10
    -  cirrusBitMask = 1 << 11
    -  mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(
    -             qa.bitwiseAnd(cirrusBitMask).eq(0))
    -  return image.updateMask(mask) \
    -      .select("B.*") \
    -      .copyProperties(image, ["system:time_start"])
    -
    -def addNDVI(image):
    -  ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi')
    -  return image.addBands(ndvi)
    -
    -withNdvi = filtered \
    -    .map(maskS2clouds) \
    -    .map(addNDVI)
    +
    def maskS2clouds(image):
    +  qa = image.select('QA60')
    +  cloudBitMask = 1 << 10
    +  cirrusBitMask = 1 << 11
    +  mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(
    +             qa.bitwiseAnd(cirrusBitMask).eq(0))
    +  return image.updateMask(mask) \
    +      .select("B.*") \
    +      .copyProperties(image, ["system:time_start"])
    +
    +def addNDVI(image):
    +  ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi')
    +  return image.addBands(ndvi)
    +
    +withNdvi = filtered \
    +    .map(maskS2clouds) \
    +    .map(addNDVI)

    Function Arguments

    @@ -4672,16 +4674,16 @@

    Function Arguments

    scale: 10, maxPixels: 1e10 }) -
    composite = withNdvi.median()
    -ndvi = composite.select('ndvi')
    -
    -stats = ndvi.reduceRegion(**{
    -  'reducer': ee.Reducer.mean(),
    -  'geometry': geometry,
    -  'scale': 10,
    -  'maxPixels': 1e10
    -  })
    +
    composite = withNdvi.median()
    +ndvi = composite.select('ndvi')
    +
    +stats = ndvi.reduceRegion(**{
    +  'reducer': ee.Reducer.mean(),
    +  'geometry': geometry,
    +  'scale': 10,
    +  'maxPixels': 1e10
    +  })

    Printing Values

    @@ -4692,8 +4694,8 @@

    Printing Values

    object.

    javascript code:

    print(stats.get('ndvi')
    -
    print(stats.get('ndvi').getInfo())
    +
    print(stats.get('ndvi').getInfo())

    In-line functions

    @@ -4704,10 +4706,10 @@

    In-line functions

    var newList = myList.map(function(number) { return ee.Number(number).pow(2); print(newList); -
    myList = ee.List.sequence(1, 10)
    -newList = myList.map(lambda number: ee.Number(number).pow(2))
    -print(newList.getInfo())
    +
    myList = ee.List.sequence(1, 10)
    +newList = myList.map(lambda number: ee.Number(number).pow(2))
    +print(newList.getInfo())

    Exercise

    @@ -4731,10 +4733,10 @@

    Exercise

    print(filtered.size());
    -
    import ee
    -ee.Authenticate()
    -ee.Initialize()
    +
    import ee
    +ee.Authenticate()
    +ee.Initialize()
    02. Automatic Conversion of Javascript Code to Python help you use Earth Engine effectively in Python.

    It comes with a function that can help you translate your javascript earth engine code to Python automatically.

    -

    Google Colab doesn’t come pre-installed with the package, so we -install it via pip.

    +

    The geemap package is pre-installed in Colab.

    +
    import geemap
    +import ee
    +
    +

    Initialization

    +

    First of all, you need to run the following cells to initialize the +API and authorize your account. You must have a Google Cloud Project +associated with your GEE account. Replace the cloud_project +with your own project from Google Cloud Console.

    try:
    -    import geemap
    -except ModuleNotFoundError:
    -    if 'google.colab' in str(get_ipython()):
    -        print('geemap not found, installing via pip in Google Colab...')
    -        !pip install geemap --quiet
    -        import geemap
    -    else:
    -        print('geemap not found, please install via conda in your environment')
    -

    The automatic conversion of code is done by calling the -geemap.js_snippet_to_py() function. We first create a -string with the javascript code.

    -
    javascript_code = """
    -var geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766]);
    -Map.centerObject(geometry, 12)
    -var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    -var rgbVis = {
    -  min: 0.0,
    -  max: 3000,
    -  bands: ['B4', 'B3', 'B2'],
    -};
    -
    -// Write a function for Cloud masking
    -function maskS2clouds(image) {
    -  var qa = image.select('QA60')
    -  var cloudBitMask = 1 << 10;
    -  var cirrusBitMask = 1 << 11;
    -  var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
    -             qa.bitwiseAnd(cirrusBitMask).eq(0))
    -  return image.updateMask(mask)
    -      .select("B.*")
    -      .copyProperties(image, ["system:time_start"])
    -}
    - 
    -var filtered = s2
    -  .filter(ee.Filter.date('2019-01-01', '2019-12-31'))
    -  .filter(ee.Filter.bounds(geometry))
    -  .map(maskS2clouds)
    -  
    -
    -// Write a function that computes NDVI for an image and adds it as a band
    -function addNDVI(image) {
    -  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi');
    -  return image.addBands(ndvi);
    -}
    -
    -var withNdvi = filtered.map(addNDVI);
    -
    -var composite = withNdvi.median()
    -palette = [
    -  'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',
    -  '74A901', '66A000', '529400', '3E8601', '207401', '056201',
    -  '004C00', '023B01', '012E01', '011D01', '011301'];
    -
    -ndviVis = {min:0, max:0.5, palette: palette }
    -Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')
    -
    -"""
    +class="sourceCode python">cloud_project = 'spatialthoughts' + +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project)
    +
    +
    +

    Automatic Conversion using GUI

    +

    geemap comes with a user interface that can be used to +interactively do code conversion. Let’s try to convert the following +Javascript code to Python.

    +
    var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]);
    +var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
    +
    +var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
    +
    +var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
    +  .filter(ee.Filter.date('2019-01-01', '2020-01-01'))
    +  .filter(ee.Filter.bounds(geometry));
    +  
    +var medianComposite = filtered.median();
    +
    +Map.centerObject(geometry, 10);
    +Map.addLayer(medianComposite, rgbVis, 'Median Composite');
    +

    Run the cell below to load the map widget. Once the map widget loads, +click the Toolbar icon in the top-right corner and select the +Convert Earth Engine Javascript to Python tool. Paste your +Javascript code and click Convert.

    lines = geemap.js_snippet_to_py(
    -    javascript_code, add_new_cell=False,
    -    import_ee=True, import_geemap=True, show_map=True)
    -for line in lines:
    -    print(line.rstrip())
    +class="sourceCode python">m = geemap.Map(width=800) +m
    +
    geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241])
    +s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    +
    +rgbVis = {'min': 0.0, 'max': 3000, 'bands': ['B4', 'B3', 'B2']}
    +
    +filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \
    +  .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \
    +  .filter(ee.Filter.bounds(geometry))
    +
    +medianComposite = filtered.median()
    +
    +m.centerObject(geometry, 10)
    +m.addLayer(medianComposite, rgbVis, 'Median Composite')
    +

    You will see the auto-converted code displayed. Copy and paste it +into a new cell and run it. Your code will be run using the GEE Python +API. If your code loads any layers, they will be loadded on the map +widget. To display it, open a new code cell and just type m +to display the widget.

    +
    m
    +
    +

    Note The auto-conversion is almost perfect and works flawlessly on +most GEE code. One place it misses is during the conversion of function +arguments specified as a dicitonary. You will need to prefix the +resulting code with ** to specify them as +**kwargs. For example, the geemap converter +produces code such as below.

    +
    stats = image.reduceRegion({
    +'reducer': ee.Reducer.mean(),
    +'geometry': geometry,
    +'scale': 10,
    +'maxPixels': 1e10
    +})
    +

    To make this valid GEE Python API code - prefix the argument +dictionary with **.

    +
    stats = image.reduceRegion(**{
    +'reducer': ee.Reducer.mean(),
    +'geometry': geometry,
    +'scale': 10,
    +'maxPixels': 1e10
    +})
    +
    + +
    +

    Automatic Conversion using Code

    +

    geemap offers a function js_snippet_to_py() +that can be used to perform the conversion using code. This is useful +for batch conversions. To use this, we first create a string with the +javascript code.

    +
    javascript_code = """
    +var geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766]);
    +Map.centerObject(geometry, 12)
    +var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    +var rgbVis = {
    +  min: 0.0,
    +  max: 3000,
    +  bands: ['B4', 'B3', 'B2'],
    +};
    +
    +// Write a function for Cloud masking
    +function maskS2clouds(image) {
    +  var qa = image.select('QA60')
    +  var cloudBitMask = 1 << 10;
    +  var cirrusBitMask = 1 << 11;
    +  var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
    +             qa.bitwiseAnd(cirrusBitMask).eq(0))
    +  return image.updateMask(mask)
    +      .select("B.*")
    +      .copyProperties(image, ["system:time_start"])
    +}
    +
    +var filtered = s2
    +  .filter(ee.Filter.date('2019-01-01', '2019-12-31'))
    +  .filter(ee.Filter.bounds(geometry))
    +  .map(maskS2clouds)
    +
    +
    +// Write a function that computes NDVI for an image and adds it as a band
    +function addNDVI(image) {
    +  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi');
    +  return image.addBands(ndvi);
    +}
    +
    +var withNdvi = filtered.map(addNDVI);
    +
    +var composite = withNdvi.median()
    +palette = [
    +  'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',
    +  '74A901', '66A000', '529400', '3E8601', '207401', '056201',
    +  '004C00', '023B01', '012E01', '011D01', '011301'];
    +
    +ndviVis = {min:0, max:0.5, palette: palette }
    +Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')
    +
    +"""
    +
    lines = geemap.js_snippet_to_py(
    +    javascript_code, add_new_cell=False,
    +    import_ee=True, import_geemap=True, show_map=True)
    +for line in lines:
    +    print(line.rstrip())

    The automatic conversion works great. Review it and paste it to the cell below.

    -
    import ee
    -import geemap
    -Map = geemap.Map()
    -
    -geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])
    -Map.centerObject(geometry, 12)
    -s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    -rgbVis = {
    -  'min': 0.0,
    -  'max': 3000,
    -  'bands': ['B4', 'B3', 'B2'],
    -}
    -
    -# Write a function for Cloud masking
    -def maskS2clouds(image):
    -  qa = image.select('QA60')
    -  cloudBitMask = 1 << 10
    -  cirrusBitMask = 1 << 11
    -  mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(
    -             qa.bitwiseAnd(cirrusBitMask).eq(0))
    -  return image.updateMask(mask) \
    -      .select("B.*") \
    -      .copyProperties(image, ["system:time_start"])
    -
    -filtered = s2 \
    -  .filter(ee.Filter.date('2019-01-01', '2019-12-31')) \
    -  .filter(ee.Filter.bounds(geometry)) \
    -  .map(maskS2clouds)
    -
    -# Write a function that computes NDVI for an image and adds it as a band
    -def addNDVI(image):
    -  ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')
    -  return image.addBands(ndvi)
    -
    -withNdvi = filtered.map(addNDVI)
    -
    -composite = withNdvi.median()
    -palette = [
    -  'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',
    -  '74A901', '66A000', '529400', '3E8601', '207401', '056201',
    -  '004C00', '023B01', '012E01', '011D01', '011301']
    -
    -ndviVis = {'min':0, 'max':0.5, 'palette': palette }
    -Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')
    -Map
    +
    import ee
    +import geemap
    +m = geemap.Map()
    +
    +geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])
    +m.centerObject(geometry, 12)
    +s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    +rgbVis = {
    +  'min': 0.0,
    +  'max': 3000,
    +  'bands': ['B4', 'B3', 'B2'],
    +}
    +
    +# Write a function for Cloud masking
    +def maskS2clouds(image):
    +  qa = image.select('QA60')
    +  cloudBitMask = 1 << 10
    +  cirrusBitMask = 1 << 11
    +  mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(
    +             qa.bitwiseAnd(cirrusBitMask).eq(0))
    +  return image.updateMask(mask) \
    +      .select("B.*") \
    +      .copyProperties(image, ["system:time_start"])
    +
    +filtered = s2 \
    +  .filter(ee.Filter.date('2019-01-01', '2019-12-31')) \
    +  .filter(ee.Filter.bounds(geometry)) \
    +  .map(maskS2clouds)
    +
    +# Write a function that computes NDVI for an image and adds it as a band
    +def addNDVI(image):
    +  ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')
    +  return image.addBands(ndvi)
    +
    +withNdvi = filtered.map(addNDVI)
    +
    +composite = withNdvi.median()
    +palette = [
    +  'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',
    +  '74A901', '66A000', '529400', '3E8601', '207401', '056201',
    +  '004C00', '023B01', '012E01', '011D01', '011301']
    +
    +ndviVis = {'min':0, 'max':0.5, 'palette': palette }
    +m.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite')
    +m
    +

    Exercise

    Take the Javascript code snippet below and use geemap to @@ -4907,92 +4990,104 @@

    03. Batch Exports

    href="https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3ASupplement%2FImage_Collections%2FExporting_ImageCollections">recommended script.

    -
    import ee
    -
    ee.Authenticate()
    -
    ee.Initialize()
    +
    +

    Initialization

    +

    First of all, you need to run the following cells to initialize the +API and authorize your account. You must have a Google Cloud Project +associated with your GEE account. Replace the cloud_project +with your own project from Google Cloud Console.

    +
    import ee
    +
    cloud_project = 'spatialthoughts'
    +
    +try:
    +    ee.Initialize(project=cloud_project)
    +except:
    +    ee.Authenticate()
    +    ee.Initialize(project=cloud_project)
    +

    Create a Collection

    -
    geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])
    -s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    -rgbVis = {
    -  'min': 0.0,
    -  'max': 3000,
    -  'bands': ['B4', 'B3', 'B2'],
    -}
    -
    -# Write a function for Cloud masking
    -def maskS2clouds(image):
    -  qa = image.select('QA60')
    -  cloudBitMask = 1 << 10
    -  cirrusBitMask = 1 << 11
    -  mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(
    -             qa.bitwiseAnd(cirrusBitMask).eq(0))
    -  return image.updateMask(mask) \
    -      .select("B.*") \
    -      .copyProperties(image, ["system:time_start"])
    -
    -filtered = s2 \
    -  .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \
    -  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \
    -  .filter(ee.Filter.bounds(geometry)) \
    -  .map(maskS2clouds)
    -
    -# Write a function that computes NDVI for an image and adds it as a band
    -def addNDVI(image):
    -  ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')
    -  return image.addBands(ndvi)
    -
    -withNdvi = filtered.map(addNDVI)
    +
    geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766])
    +s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED')
    +rgbVis = {
    +  'min': 0.0,
    +  'max': 3000,
    +  'bands': ['B4', 'B3', 'B2'],
    +}
    +
    +# Write a function for Cloud masking
    +def maskS2clouds(image):
    +  qa = image.select('QA60')
    +  cloudBitMask = 1 << 10
    +  cirrusBitMask = 1 << 11
    +  mask = qa.bitwiseAnd(cloudBitMask).eq(0).And(
    +             qa.bitwiseAnd(cirrusBitMask).eq(0))
    +  return image.updateMask(mask) \
    +      .select("B.*") \
    +      .copyProperties(image, ["system:time_start"])
    +
    +filtered = s2 \
    +  .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \
    +  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \
    +  .filter(ee.Filter.bounds(geometry)) \
    +  .map(maskS2clouds)
    +
    +# Write a function that computes NDVI for an image and adds it as a band
    +def addNDVI(image):
    +  ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi')
    +  return image.addBands(ndvi)
    +
    +withNdvi = filtered.map(addNDVI)

    Export All Images

    Exports are done via the ee.batch module. This module allows you to automatically start an export - making it suitable for batch exports.

    -
    image_ids = withNdvi.aggregate_array('system:index').getInfo()
    -print('Total images: ', len(image_ids))
    -
    # Export with 100m resolution for this demo
    -for i, image_id in enumerate(image_ids):
    -  image = ee.Image(withNdvi.filter(ee.Filter.eq('system:index', image_id)).first())
    -  task = ee.batch.Export.image.toDrive(**{
    -    'image': image.select('ndvi'),
    -    'description': 'Image Export {}'.format(i+1),
    -    'fileNamePrefix': image_id,
    -    'folder':'earthengine',
    -    'scale': 100,
    -    'region': image.geometry(),
    -    'maxPixels': 1e10
    -  })
    -  task.start()
    -  print('Started Task: ', i+1)
    +
    image_ids = withNdvi.aggregate_array('system:index').getInfo()
    +print('Total images: ', len(image_ids))
    +
    # Export with 100m resolution for this demo
    +for i, image_id in enumerate(image_ids):
    +  image = ee.Image(withNdvi.filter(ee.Filter.eq('system:index', image_id)).first())
    +  task = ee.batch.Export.image.toDrive(**{
    +    'image': image.select('ndvi'),
    +    'description': 'Image Export {}'.format(i+1),
    +    'fileNamePrefix': image_id,
    +    'folder':'earthengine',
    +    'scale': 100,
    +    'region': image.geometry(),
    +    'maxPixels': 1e10
    +  })
    +  task.start()
    +  print('Started Task: ', i+1)

    Manage Running/Waiting Tasks

    You can manage tasks as well. Get a list of tasks and get state information on them

    -
    tasks = ee.batch.Task.list()
    -for task in tasks:
    -  task_id = task.status()['id']
    -  task_state = task.status()['state']
    -  print(task_id, task_state)
    +
    tasks = ee.batch.Task.list()
    +for task in tasks:
    +  task_id = task.status()['id']
    +  task_state = task.status()['state']
    +  print(task_id, task_state)

    You can cancel tasks as well

    -
    tasks = ee.batch.Task.list()
    -for task in tasks:
    -    task_id = task.status()['id']
    -    task_state = task.status()['state']
    -    if task_state == 'RUNNING' or task_state == 'READY':
    -        task.cancel()
    -        print('Task {} canceled'.format(task_id))
    -    else:
    -        print('Task {} state is {}'.format(task_id, task_state))
    +
    tasks = ee.batch.Task.list()
    +for task in tasks:
    +    task_id = task.status()['id']
    +    task_state = task.status()['state']
    +    if task_state == 'RUNNING' or task_state == 'READY':
    +        task.cancel()
    +        print('Task {} canceled'.format(task_id))
    +    else:
    +        print('Task {} state is {}'.format(task_id, task_state))

    Exercise

    @@ -5007,38 +5102,38 @@

    Exercise

  • Hint2: You need to export the image contained in the clippedImage variable
  • -
    import ee
    -
    -lsib = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')
    -australia = lsib.filter(ee.Filter.eq('country_na', 'Australia'))
    -geometry = australia.geometry()
    -
    -terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')
    -tmax = terraclimate.select('tmmx')
    -
    -def scale(image):
    -  return image.multiply(0.1) \
    -    .copyProperties(image,['system:time_start'])
    -
    -tmaxScaled = tmax.map(scale)
    -
    -filtered = tmaxScaled \
    -  .filter(ee.Filter.date('2020-01-01', '2021-01-01')) \
    -  .filter(ee.Filter.bounds(geometry))
    -
    -image_ids = filtered.aggregate_array('system:index').getInfo()
    -print('Total images: ', len(image_ids))
    +
    import ee
    +
    +lsib = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')
    +australia = lsib.filter(ee.Filter.eq('country_na', 'Australia'))
    +geometry = australia.geometry()
    +
    +terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')
    +tmax = terraclimate.select('tmmx')
    +
    +def scale(image):
    +  return image.multiply(0.1) \
    +    .copyProperties(image,['system:time_start'])
    +
    +tmaxScaled = tmax.map(scale)
    +
    +filtered = tmaxScaled \
    +  .filter(ee.Filter.date('2020-01-01', '2021-01-01')) \
    +  .filter(ee.Filter.bounds(geometry))
    +
    +image_ids = filtered.aggregate_array('system:index').getInfo()
    +print('Total images: ', len(image_ids))

    Replace the comments with your code.

    -
    for i, image_id in enumerate(image_ids):
    -    exportImage = ee.Image(filtered.filter(ee.Filter.eq('system:index', image_id)).first())
    -    # Clip the image to the region geometry
    -    clippedImage = exportImage.clip(geometry)
    -
    -    ## Create the export task using ee.batch.Export.image.toDrive()
    -
    -    ## Start the task
    +
    for i, image_id in enumerate(image_ids):
    +    exportImage = ee.Image(filtered.filter(ee.Filter.eq('system:index', image_id)).first())
    +    # Clip the image to the region geometry
    +    clippedImage = exportImage.clip(geometry)
    +
    +    ## Create the export task using ee.batch.Export.image.toDrive()
    +
    +    ## Start the task
    Launching multiple tasks using the  Python API

    @@ -5064,100 +5159,106 @@

    04. Creating Charts in Python

  • geemap Example notebook
  • -
    import ee
    -
    try:
    -    import geemap
    -except ModuleNotFoundError:
    -    if 'google.colab' in str(get_ipython()):
    -        print('geemap not found, installing via pip in Google Colab...')
    -        !pip install geemap --quiet
    -        import geemap
    -    else:
    -        print('geemap not found, please install via conda in your environment')
    -
    ee.Authenticate()
    -
    ee.Initialize()
    -

    Load the TerraClimate collection and select the ‘tmmx’ band.

    -
    terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')
    -tmax = terraclimate.select('tmmx')
    -

    Define a point location for the chart.

    +
    +

    Initialization

    +

    First of all, you need to run the following cells to initialize the +API and authorize your account. You must have a Google Cloud Project +associated with your GEE account. Replace the cloud_project +with your own project from Google Cloud Console.

    geometry = ee.Geometry.Point([77.57738128916243, 12.964758918835752])
    -

    Scale the band values so they are in Degree Celcius.

    +class="sourceCode python">import geemap +import ee
    def scale_image(image):
    -  return ee.Image(image).multiply(0.1)\
    -    .copyProperties(image, ['system:time_start'])
    -
    -tmaxScaled = tmax.map(scale_image)
    -

    Filter the collection.

    +class="sourceCode python">cloud_project = 'spatialthoughts' + +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project)
    + +
    +

    Load and Process the Data

    +

    Load the TerraClimate collection and select the ‘tmmx’ band.

    filtered = tmaxScaled.filter(ee.Filter.date('2019-01-01', '2020-01-01')) \
    -                     .filter(ee.Filter.bounds(geometry))
    -

    To chart an image series in Python, we must first extract the values -from each image and create a FeatureCollection.

    +class="sourceCode python">terraclimate = ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE') +tmax = terraclimate.select('tmmx')
    +

    Define a point location for the chart.

    def extract_data(image):
    -    stats = image.reduceRegion(**{ 
    -        'reducer':ee.Reducer.mean(),
    -        'geometry':geometry,
    -        'scale':5000
    -    })
    -    properties = {
    -        'month': image.get('system:index'),
    -        'tmmx': stats.get('tmmx')
    -    }
    -    return ee.Feature(None, properties)
    -
    -data = ee.FeatureCollection(filtered.map(extract_data))
    +class="sourceCode python">geometry = ee.Geometry.Point([77.57738128916243, 12.964758918835752]) +

    Scale the band values so they are in Degree Celcius.

    print(data.first().getInfo())
    -
    -

    Create an Interactive Chart using geemap

    +class="sourceCode python">def scale_image(image): + return ee.Image(image).multiply(0.1)\ + .copyProperties(image, ['system:time_start']) + +tmaxScaled = tmax.map(scale_image)
    +

    Filter the collection.

    from geemap import chart
    +class="sourceCode python">filtered = tmaxScaled.filter(ee.Filter.date('2019-01-01', '2020-01-01')) \ + .filter(ee.Filter.bounds(geometry)) +

    To chart an image series in Python, we must first extract the values +from each image and create a FeatureCollection.

    options = {
    -    'title': 'Max Monthly Temperature at Bangalore', 
    -    'legend_location': 'top-right',
    -    'height': '500px',
    -    'ylabel': 'Temperature (C)',
    -    'xlabel': 'Date',
    -    'colors': ['blue']
    -}
    +class="sourceCode python">def extract_data(image): + stats = image.reduceRegion(**{ + 'reducer':ee.Reducer.mean(), + 'geometry':geometry, + 'scale':5000 + }) + properties = { + 'month': image.get('system:index'), + 'tmmx': stats.get('tmmx') + } + return ee.Feature(None, properties) + +data = ee.FeatureCollection(filtered.map(extract_data))
    chart.feature_byFeature(data, 'month', ['tmmx'], **options)
    +class="sourceCode python">print(data.first().getInfo()) -
    -

    Create a chart using Matplotlib

    -

    We can convert a FeatureCollection to a DataFrame using -geemap helper function ee_to_pandas.

    +
    +

    Create an Interactive Chart using geemap

    import geemap
    -df = geemap.ee_to_pandas(data)
    +class="sourceCode python">from geemap import chart
    df
    -

    Now we have a regular Pandas dataframe that can be plotted with -matplotlib.

    +class="sourceCode python">options = { + 'title': 'Max Monthly Temperature at Bangalore', + 'legend_location': 'top-right', + 'height': '500px', + 'ylabel': 'Temperature (C)', + 'xlabel': 'Date', + 'colors': ['blue'] +}
    %matplotlib inline
    -import matplotlib.pyplot as plt
    +class="sourceCode python">chart.feature_byFeature(data, 'month', ['tmmx'], **options) + +
    +

    Create a chart using Matplotlib

    +

    We can convert a FeatureCollection to a DataFrame using +geemap helper function ee_to_pandas.

    fig, ax = plt.subplots()
    -fig.set_size_inches(20,10)
    -
    -
    -df.plot(ax=ax,
    -        title='Max Monthly Temperature at Bangalore',
    -        x='month',
    -        ylabel='Temperature (C)',
    -        kind='line')
    -plt.tight_layout()
    +class="sourceCode python">import geemap +df = geemap.ee_to_pandas(data)
    +
    df
    +

    Now we have a regular Pandas dataframe that can be plotted with +matplotlib.

    +
    %matplotlib inline
    +import matplotlib.pyplot as plt
    +
    fig, ax = plt.subplots()
    +fig.set_size_inches(20,10)
    +
    +
    +df.plot(ax=ax,
    +        title='Max Monthly Temperature at Bangalore',
    +        x='month',
    +        ylabel='Temperature (C)',
    +        kind='line')
    +plt.tight_layout()

    Exercise

    @@ -5193,68 +5294,74 @@

    05. Automating Downloads

  • Create a new file named download_data.py with the content shown below.
  • -
    import datetime
    -import ee
    -import csv
    -import os
    -
    -ee.Initialize()
    -
    -# Get current date and convert to milliseconds 
    -start_date = ee.Date.fromYMD(2022, 1, 1)
    -end_date = start_date.advance(1, 'month')
    -
    -date_string = end_date.format('YYYY_MM')
    -filename = 'ssm_{}.csv'.format(date_string.getInfo())
    -
    -# Saving to current directory. You can change the path to appropriate location
    -output_path = os.path.join(filename)
    -
    -# Datasets
    -# SMAP is in safe mode and not generating new data since August 2022
    -# https://nsidc.org/data/user-resources/data-announcements/user-notice-smap-safe-mode
    -soilmoisture = ee.ImageCollection("NASA_USDA/HSL/SMAP10KM_soil_moisture")
    -admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2")
    -
    -# Filter to a state
    -karnataka = admin2.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
    -
    -# Select the ssm band
    -ssm  = soilmoisture.select('ssm')
    -
    -filtered = ssm .filter(ee.Filter.date(start_date, end_date))
    -
    -mean = filtered.mean()
    -
    -stats = mean.reduceRegions(**{
    -  'collection': karnataka,
    -  'reducer': ee.Reducer.mean().setOutputs(['meanssm']),
    -  'scale': 10000,
    -  'crs': 'EPSG:32643'
    -  })
    -
    -# Select columns to keep and remove geometry to make the result lightweight
    -# Change column names to match your uploaded shapefile
    -columns = ['ADM2_NAME', 'meanssm']
    -exportCollection = stats.select(**{
    -    'propertySelectors': columns,
    -    'retainGeometry': False})
    -
    -features = exportCollection.getInfo()['features']
    -
    -data = []
    -
    -for f in features:
    -    data.append(f['properties'])
    -
    -field_names = ['ADM2_NAME', 'meanssm']
    -
    -with open(output_path, 'w') as csvfile:
    -    writer = csv.DictWriter(csvfile, fieldnames = field_names)
    -    writer.writeheader()
    -    writer.writerows(data)
    -    print('Success: File written at', output_path)
    +
    import datetime
    +import ee
    +import csv
    +import os
    +
    +cloud_project = 'spatialthoughts'
    +
    +try:
    +    ee.Initialize(project=cloud_project)
    +except:
    +    ee.Authenticate()
    +    ee.Initialize(project=cloud_project)
    +
    +# Get current date and convert to milliseconds 
    +start_date = ee.Date.fromYMD(2022, 1, 1)
    +end_date = start_date.advance(1, 'month')
    +
    +date_string = end_date.format('YYYY_MM')
    +filename = 'ssm_{}.csv'.format(date_string.getInfo())
    +
    +# Saving to current directory. You can change the path to appropriate location
    +output_path = os.path.join(filename)
    +
    +# Datasets
    +# SMAP is in safe mode and not generating new data since August 2022
    +# https://nsidc.org/data/user-resources/data-announcements/user-notice-smap-safe-mode
    +soilmoisture = ee.ImageCollection("NASA_USDA/HSL/SMAP10KM_soil_moisture")
    +admin2 = ee.FeatureCollection("FAO/GAUL_SIMPLIFIED_500m/2015/level2")
    +
    +# Filter to a state
    +karnataka = admin2.filter(ee.Filter.eq('ADM1_NAME', 'Karnataka'))
    +
    +# Select the ssm band
    +ssm  = soilmoisture.select('ssm')
    +
    +filtered = ssm .filter(ee.Filter.date(start_date, end_date))
    +
    +mean = filtered.mean()
    +
    +stats = mean.reduceRegions(**{
    +  'collection': karnataka,
    +  'reducer': ee.Reducer.mean().setOutputs(['meanssm']),
    +  'scale': 10000,
    +  'crs': 'EPSG:32643'
    +  })
    +
    +# Select columns to keep and remove geometry to make the result lightweight
    +# Change column names to match your uploaded shapefile
    +columns = ['ADM2_NAME', 'meanssm']
    +exportCollection = stats.select(**{
    +    'propertySelectors': columns,
    +    'retainGeometry': False})
    +
    +features = exportCollection.getInfo()['features']
    +
    +data = []
    +
    +for f in features:
    +    data.append(f['properties'])
    +
    +field_names = ['ADM2_NAME', 'meanssm']
    +
    +with open(output_path, 'w') as csvfile:
    +    writer = csv.DictWriter(csvfile, fieldnames = field_names)
    +    writer.writeheader()
    +    writer.writerows(data)
    +    print('Success: File written at', output_path)
    1. From the terminal, navigate to the directory where you have created the file and type the command below to run the script.
    2. diff --git a/end-to-end-gee-output/01_python_api_syntax.md b/end-to-end-gee-output/01_python_api_syntax.md index f8eeee9f..eef16816 100644 --- a/end-to-end-gee-output/01_python_api_syntax.md +++ b/end-to-end-gee-output/01_python_api_syntax.md @@ -4,7 +4,9 @@ Coming from the programming in Earth Engine through the Code Editor, you will ne #### Initialization -First of all, you need to run the following cells to initialize the API and authorize your account. You will be prompted to sign-in to the account and allow access to *View and Manage your Earth Engine data*. Once you approve, you will get an a verification code that needs to be entered at the prompt. This step needs to be done just once per session. +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). + +You will be prompted to allow the notebook to access your Google credentials to sign-in to the account and allow access to *Google Drive and Google Cloud data*. Once you approve, it will proceed to initialize the Earth Engine API. This step needs to be done just once per session. ```python @@ -13,12 +15,14 @@ import ee ```python -ee.Authenticate() -``` +cloud_project = 'spatialthoughts' +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) -```python -ee.Initialize() ``` #### Variables diff --git a/end-to-end-gee-output/02_automatic_conversion_of_scripts.md b/end-to-end-gee-output/02_automatic_conversion_of_scripts.md index 6037a5d9..8597bfc0 100644 --- a/end-to-end-gee-output/02_automatic_conversion_of_scripts.md +++ b/end-to-end-gee-output/02_automatic_conversion_of_scripts.md @@ -1,23 +1,107 @@ -[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python. +[geemap](https://github.com/giswqs/geemap) is an open-source Python package that comes with many helpful features that help you use Earth Engine effectively in Python. It comes with a function that can help you translate your javascript earth engine code to Python automatically. -Google Colab doesn't come pre-installed with the package, so we install it via pip. +The `geemap` package is pre-installed in Colab. ```python +import geemap +import ee +``` + +#### Initialization + +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). + + +```python +cloud_project = 'spatialthoughts' + try: - import geemap -except ModuleNotFoundError: - if 'google.colab' in str(get_ipython()): - print('geemap not found, installing via pip in Google Colab...') - !pip install geemap --quiet - import geemap - else: - print('geemap not found, please install via conda in your environment') + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) +``` + +#### Automatic Conversion using GUI + +`geemap` comes with a user interface that can be used to interactively do code conversion. Let's try to convert the following Javascript code to Python. + +``` +var geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]); +var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED'); + +var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']}; + +var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) + .filter(ee.Filter.date('2019-01-01', '2020-01-01')) + .filter(ee.Filter.bounds(geometry)); + +var medianComposite = filtered.median(); + +Map.centerObject(geometry, 10); +Map.addLayer(medianComposite, rgbVis, 'Median Composite'); +``` + +Run the cell below to load the map widget. Once the map widget loads, click the *Toolbar* icon in the top-right corner and select the *Convert Earth Engine Javascript to Python* tool. Paste your Javascript code and click *Convert*. + + +```python +m = geemap.Map(width=800) +m ``` -The automatic conversion of code is done by calling the `geemap.js_snippet_to_py()` function. We first create a string with the javascript code. + +```python +geometry = ee.Geometry.Point([77.60412933051538, 12.952912912328241]) +s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED') + +rgbVis = {'min': 0.0, 'max': 3000, 'bands': ['B4', 'B3', 'B2']} + +filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) \ + .filter(ee.Filter.date('2019-01-01', '2020-01-01')) \ + .filter(ee.Filter.bounds(geometry)) + +medianComposite = filtered.median() + +m.centerObject(geometry, 10) +m.addLayer(medianComposite, rgbVis, 'Median Composite') + +``` + +You will see the auto-converted code displayed. Copy and paste it into a new cell and run it. Your code will be run using the GEE Python API. If your code loads any layers, they will be loadded on the map widget. To display it, open a new code cell and just type `m` to display the widget. + + + + +```python +m +``` + +> Note The auto-conversion is almost perfect and works flawlessly on most GEE code. One place it misses is during the conversion of function arguments specified as a dicitonary. You will need to prefix the resulting code with `**` to specify them as `**kwargs`. For example, the `geemap` converter produces code such as below. + ``` + stats = image.reduceRegion({ + 'reducer': ee.Reducer.mean(), + 'geometry': geometry, + 'scale': 10, + 'maxPixels': 1e10 + }) + ``` +To make this valid GEE Python API code - prefix the argument dictionary with `**`. + ``` + stats = image.reduceRegion(**{ + 'reducer': ee.Reducer.mean(), + 'geometry': geometry, + 'scale': 10, + 'maxPixels': 1e10 + }) + ``` + +#### Automatic Conversion using Code + +`geemap` offers a function `js_snippet_to_py()` that can be used to perform the conversion using code. This is useful for batch conversions. To use this, we first create a string with the javascript code. ```python @@ -42,12 +126,12 @@ function maskS2clouds(image) { .select("B.*") .copyProperties(image, ["system:time_start"]) } - + var filtered = s2 .filter(ee.Filter.date('2019-01-01', '2019-12-31')) .filter(ee.Filter.bounds(geometry)) .map(maskS2clouds) - + // Write a function that computes NDVI for an image and adds it as a band function addNDVI(image) { @@ -84,10 +168,10 @@ The automatic conversion works great. Review it and paste it to the cell below. ```python import ee import geemap -Map = geemap.Map() +m = geemap.Map() geometry = ee.Geometry.Point([107.61303468448624, 12.130969369851766]) -Map.centerObject(geometry, 12) +m.centerObject(geometry, 12) s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED') rgbVis = { 'min': 0.0, @@ -125,8 +209,8 @@ palette = [ '004C00', '023B01', '012E01', '011D01', '011301'] ndviVis = {'min':0, 'max':0.5, 'palette': palette } -Map.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite') -Map +m.addLayer(withNdvi.select('ndvi'), ndviVis, 'NDVI Composite') +m ``` ### Exercise diff --git a/end-to-end-gee-output/03_export_a_collection.md b/end-to-end-gee-output/03_export_a_collection.md index 1efa3c4d..29b92c66 100644 --- a/end-to-end-gee-output/03_export_a_collection.md +++ b/end-to-end-gee-output/03_export_a_collection.md @@ -2,19 +2,24 @@ One of the most commonly asked questions by Earth Engine users is - *How do I do > You can also export images in a collection using Javascript API in the Code Editor but this requires you to manually start the tasks for each image. This approach is fine for small number of images. You can check out the [recommended script](https://code.earthengine.google.co.in/?scriptPath=users%2Fujavalgandhi%2FEnd-to-End-GEE%3ASupplement%2FImage_Collections%2FExporting_ImageCollections). +#### Initialization -```python -import ee -``` +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). ```python -ee.Authenticate() +import ee ``` ```python -ee.Initialize() +cloud_project = 'spatialthoughts' + +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) ``` #### Create a Collection diff --git a/end-to-end-gee-output/04_creating_charts.md b/end-to-end-gee-output/04_creating_charts.md index b69f4ea3..a2a9b46f 100644 --- a/end-to-end-gee-output/04_creating_charts.md +++ b/end-to-end-gee-output/04_creating_charts.md @@ -8,34 +8,29 @@ References: - geemap [Example notebook](https://geemap.org/notebooks/63_charts/) +#### Initialization -```python -import ee -``` +First of all, you need to run the following cells to initialize the API and authorize your account. You must have a Google Cloud Project associated with your GEE account. Replace the `cloud_project` with your own project from [Google Cloud Console](https://console.cloud.google.com/). ```python -try: - import geemap -except ModuleNotFoundError: - if 'google.colab' in str(get_ipython()): - print('geemap not found, installing via pip in Google Colab...') - !pip install geemap --quiet - import geemap - else: - print('geemap not found, please install via conda in your environment') +import geemap +import ee ``` ```python -ee.Authenticate() -``` - +cloud_project = 'spatialthoughts' -```python -ee.Initialize() +try: + ee.Initialize(project=cloud_project) +except: + ee.Authenticate() + ee.Initialize(project=cloud_project) ``` +#### Load and Process the Data + Load the TerraClimate collection and select the 'tmmx' band. @@ -75,7 +70,7 @@ To chart an image series in Python, we must first extract the values from each i ```python def extract_data(image): - stats = image.reduceRegion(**{ + stats = image.reduceRegion(**{ 'reducer':ee.Reducer.mean(), 'geometry':geometry, 'scale':5000 @@ -94,7 +89,7 @@ data = ee.FeatureCollection(filtered.map(extract_data)) print(data.first().getInfo()) ``` -### Create an Interactive Chart using geemap +#### Create an Interactive Chart using geemap ```python @@ -104,7 +99,7 @@ from geemap import chart ```python options = { - 'title': 'Max Monthly Temperature at Bangalore', + 'title': 'Max Monthly Temperature at Bangalore', 'legend_location': 'top-right', 'height': '500px', 'ylabel': 'Temperature (C)', @@ -118,7 +113,7 @@ options = { chart.feature_byFeature(data, 'month', ['tmmx'], **options) ``` -### Create a chart using Matplotlib +#### Create a chart using Matplotlib We can convert a FeatureCollection to a DataFrame using `geemap` helper function `ee_to_pandas`.