{ "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": 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", "---" ] } ], "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 }