{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Pydeck Earth Engine Introduction\n", "\n", "This is an introduction to using [Pydeck](https://pydeck.gl) and [Deck.gl](https://deck.gl) with [Google Earth Engine](https://earthengine.google.com/) in Jupyter Notebooks.\n", "\n", "To see this example online, view the [JavaScript version][js-example].\n", "\n", "[js-example]: https://earthengine-layers.com/examples/image" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To run this notebook locally, you'll need to install some dependencies. Installing into a new Conda environment is recommended. To create and enter the environment, make sure you have [Conda installed](https://www.anaconda.com/products/individual), then run:\n", "\n", "```bash\n", "conda create -n pydeck-ee -c conda-forge python jupyter jupyterlab notebook pydeck earthengine-api nodejs -y\n", "conda activate pydeck-ee\n", "\n", "# Install the pydeck-earthengine-layers package from pip\n", "pip install pydeck-earthengine-layers\n", "\n", "# If using Jupyter Notebook:\n", "jupyter nbextension install --sys-prefix --symlink --overwrite --py pydeck\n", "jupyter nbextension enable --sys-prefix --py pydeck\n", "\n", "# If using Jupyter Lab\n", "jupyter labextension install @jupyter-widgets/jupyterlab-manager\n", "DECKGL_SEMVER=`python -c \"import pydeck; print(pydeck.frontend_semver.DECKGL_SEMVER)\"`\n", "jupyter labextension install @deck.gl/jupyter-widget@$DECKGL_SEMVER\n", "```\n", "\n", "then open Jupyter Notebook with `jupyter notebook` or Jupyter Lab with `jupyter lab`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now in a Python Jupyter Notebook, let's first import required packages:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pydeck_earthengine_layers import EarthEngineLayer\n", "import pydeck as pdk\n", "import ee" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Authenticate with Earth Engine\n", "\n", "Using Earth Engine requires authentication. If you don't have a Google account approved for use with Earth Engine, you'll need to request access. For more information and to sign up, go to https://signup.earthengine.google.com/." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you haven't used Earth Engine in Python before, the next block will create a prompt which waits for user input. If you don't see a prompt, you may need to authenticate on the command line with `earthengine authenticate` and then restart the notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "try:\n", " ee.Initialize()\n", "except Exception as e:\n", " ee.Authenticate()\n", " ee.Initialize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Elevation data example\n", "\n", "Now let's make a simple example using [Shuttle Radar Topography Mission (SRTM)][srtm] elevation data. Here we create an `ee.Image` object referencing that dataset.\n", "\n", "[srtm]: https://developers.google.com/earth-engine/datasets/catalog/CGIAR_SRTM90_V4" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "image = ee.Image('CGIAR/SRTM90_V4')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here `vis_params` consists of parameters that will be passed to the Earth Engine [`visParams` argument][visparams]. Any parameters that you could pass directly to Earth Engine in the code editor, you can also pass here to the `EarthEngineLayer`.\n", "\n", "[visparams]: https://developers.google.com/earth-engine/image_visualization" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "vis_params={\n", " \"min\": 0, \n", " \"max\": 4000,\n", " \"palette\": ['006633', 'E5FFCC', '662A00', 'D8D8D8', 'F5F5F5']\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we're ready to create the Pydeck layer. The `EarthEngineLayer` makes this simple. Just pass the Earth Engine object to the class." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Including the `id` argument isn't necessary when you only have one pydeck layer, but it is necessary to distinguish multiple layers, so it's good to get into the habit of including an `id` parameter." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ee_layer = EarthEngineLayer(\n", " image,\n", " vis_params,\n", " id=\"SRTM_layer\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then just pass this layer to a `pydeck.Deck` instance, and call `.show()` to create a map:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "view_state = pdk.ViewState(latitude=37.7749295, longitude=-122.4194155, zoom=10, bearing=0, pitch=45)\n", "r = pdk.Deck(\n", " layers=[ee_layer], \n", " initial_view_state=view_state\n", ")\n", "r.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hillshade Example\n", "\n", "As a slightly more in-depth example, let's use the SRTM dataset to calculate hillshading. This example comes from [giswqs/earthengine-py-notebooks][giswqs/earthengine-py-notebooks]:\n", "\n", "[giswqs/earthengine-py-notebooks]: https://github.com/giswqs/earthengine-py-notebooks/blob/master/Visualization/hillshade.ipynb" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Add Earth Engine dataset\n", "import math\n", "\n", "def Radians(img):\n", " return img.toFloat().multiply(math.pi).divide(180)\n", "\n", "def Hillshade(az, ze, slope, aspect):\n", " \"\"\"Compute hillshade for the given illumination az, el.\"\"\"\n", " azimuth = Radians(ee.Image(az))\n", " zenith = Radians(ee.Image(ze))\n", " # Hillshade = cos(Azimuth - Aspect) * sin(Slope) * sin(Zenith) +\n", " # cos(Zenith) * cos(Slope)\n", " return (azimuth.subtract(aspect).cos()\n", " .multiply(slope.sin())\n", " .multiply(zenith.sin())\n", " .add(\n", " zenith.cos().multiply(slope.cos())))\n", "\n", "terrain = ee.Algorithms.Terrain(ee.Image('srtm90_v4'))\n", "slope_img = Radians(terrain.select('slope'))\n", "aspect_img = Radians(terrain.select('aspect'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "ee_object = Hillshade(0, 60, slope_img, aspect_img)\n", "ee_layer = EarthEngineLayer(ee_object)\n", "view_state = pdk.ViewState(latitude=36.0756, longitude=-111.9987, zoom=7, bearing=0, pitch=30)\n", "r = pdk.Deck(\n", " layers=[ee_layer], \n", " initial_view_state=view_state\n", ")\n", "r.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" } }, "nbformat": 4, "nbformat_minor": 4 }