Skip to content

Instantly share code, notes, and snippets.

@jdbcode
Last active April 23, 2024 18:28
Show Gist options
  • Save jdbcode/74c013f8e9909764210aa743351e7944 to your computer and use it in GitHub Desktop.
Save jdbcode/74c013f8e9909764210aa743351e7944 to your computer and use it in GitHub Desktop.
Intro to Earth Engine with Python shown at EGU 2024. An example of calculating the difference NDVI for riparian and upland regions of a watershed. Operations are common GIS vector and raster tasks.
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/jdbcode/74c013f8e9909764210aa743351e7944/intro_to_earth_engine_with_python_ndvi.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# Setup"
],
"metadata": {
"id": "_86f47l8lFvy"
}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QFVnLbu1LqIO"
},
"outputs": [],
"source": [
" import ee\n",
" import geemap\n",
" import geemap.colormaps as cm\n",
" from google.colab import _frontend\n",
" import pandas as pd\n",
" import altair as alt"
]
},
{
"cell_type": "code",
"source": [
"ee.Authenticate()\n",
"ee.Initialize(project='MY-PROJECT')"
],
"metadata": {
"id": "LW8m6mX6Lt-6"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Add a Map panel and define a print helper\n",
"\n",
"*BE SURE TO RUN THE SCRATCH CELL TO INSTANTIATE THE MAP*\n",
"\n"
],
"metadata": {
"id": "leERuRU8kngf"
}
},
{
"cell_type": "code",
"source": [
"_frontend.create_scratch_cell(\"#@title Map\\nm = geemap.Map(draw_ctrl=False)\\nm\", False)"
],
"metadata": {
"id": "RL7sAW0gO2Hk"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def print_table(col, name):\n",
" def get_ic_props(ic):\n",
" def to_props(i):\n",
" return ee.Feature(None, i.toDictionary())\n",
" return ic.map(to_props)\n",
" if str(type(col)) == \"<class 'ee.imagecollection.ImageCollection'>\":\n",
" col = get_ic_props(col)\n",
"\n",
" df = ee.data.computeFeatures({\n",
" 'expression': col, 'fileFormat': 'PANDAS_DATAFRAME'})\n",
" df = df.drop('geo', axis=1)\n",
"\n",
" display(name, df)"
],
"metadata": {
"id": "0Q_MZCn_25pB"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# Vector analysis\n",
"\n",
"## Load data and display"
],
"metadata": {
"id": "txThCaSPHeqq"
}
},
{
"cell_type": "code",
"source": [
"basins = ee.FeatureCollection('WWF/HydroATLAS/v1/Basins/level06')\n",
"rivers = ee.FeatureCollection('WWF/HydroSHEDS/v1/FreeFlowingRivers')\n",
"\n",
"\n",
"m.add_layer(basins, {'color': 'grey'}, 'Level 6 basins')\n",
"m.add_layer(rivers, {'color': 'blue'}, 'Rivers')\n",
"m.center_object(ee.Geometry.Point([-118.3430, 46.0646]), 7)\n",
"\n",
"\n",
"print_table(basins.limit(5), 'basins')\n",
"print_table(rivers.limit(5), 'rivers')"
],
"metadata": {
"id": "6UHNS-_li-v2"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Filtering"
],
"metadata": {
"id": "eG7i4S6aHiIN"
}
},
{
"cell_type": "markdown",
"source": [
"### By attribute: Walla Walla basin by ID"
],
"metadata": {
"id": "EjBhOVwOS-aN"
}
},
{
"cell_type": "code",
"source": [
"wawa_basin = basins.filter('HYBAS_ID == 7060382460')\n",
"\n",
"m.add_layer(wawa_basin, {'color': 'yellow'}, 'Walla Walla basin')"
],
"metadata": {
"id": "GugdnDc3IRLw"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### By intersection: River segments in Walla Walla basin"
],
"metadata": {
"id": "FYRA8HC56JeW"
}
},
{
"cell_type": "code",
"source": [
"main_rivers = rivers.filterBounds(wawa_basin).filter('RIV_ORD <= 6')\n",
"\n",
"m.add_layer(main_rivers, {'color': 'blue'}, 'Rivers')"
],
"metadata": {
"id": "1k8BVJZ0IPIo"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Buffer the river segments to define riparian region"
],
"metadata": {
"id": "liEmitY3FnN7"
}
},
{
"cell_type": "code",
"source": [
"riparian = main_rivers.geometry().buffer(100, 1)\n",
"\n",
"m.add_layer(riparian, {'color': 'black'}, 'Main rivers buffer')"
],
"metadata": {
"id": "4oKZoWdmWfJv"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Clip the Walla Walla basin by the riparian region to define upland"
],
"metadata": {
"id": "SEkTjNZaXjTD"
}
},
{
"cell_type": "code",
"source": [
"upland = wawa_basin.geometry().difference(riparian)\n",
"\n",
"m.add_layer(upland, {'color': 'orange'}, 'Upland')"
],
"metadata": {
"id": "A652vH5OXhuJ"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# Raster analysis"
],
"metadata": {
"id": "udAkTHv2xw5D"
}
},
{
"cell_type": "markdown",
"source": [
"## Collection filtering"
],
"metadata": {
"id": "gHKnOvA8yRdS"
}
},
{
"cell_type": "code",
"source": [
"toa_col = (\n",
" ee.ImageCollection('LANDSAT/LC09/C02/T1_TOA')\n",
" .filterDate('2022-04-01', '2022-11-01')\n",
" .filterBounds(wawa_basin)\n",
" .filter('CLOUD_COVER < 1')\n",
")\n",
"\n",
"print_table(toa_col, 'Images')"
],
"metadata": {
"id": "_-HFyHaX6VGT"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Image display"
],
"metadata": {
"id": "EfoQxWNoyV6k"
}
},
{
"cell_type": "code",
"source": [
"false_color_vis = {\n",
" 'bands': ['B6', 'B5', 'B3'],\n",
" 'min': 0,\n",
" 'max': 0.4\n",
"}\n",
"m.add_layer(toa_col.first(), false_color_vis, 'TOA (first)')"
],
"metadata": {
"id": "MYOB3-iY7HGW"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Image math\n",
"\n",
"Let's use band math to calculate NDVI and NBR. Define a function to perform the calculation so we can map the function over the image collection."
],
"metadata": {
"id": "GUwf80sy2gdj"
}
},
{
"cell_type": "code",
"source": [
"def calc_ndvi(image):\n",
" ndvi = ee.Image().expression(\n",
" 'ndvi = (nir-red)/(nir+red)',\n",
" {\n",
" 'nir': image.select('B5'),\n",
" 'red': image.select('B4')\n",
" }\n",
" )\n",
"\n",
" return image.addBands([ndvi])"
],
"metadata": {
"id": "NlUu69Sv8qTV"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Function mapping"
],
"metadata": {
"id": "66j49Tkw9s9F"
}
},
{
"cell_type": "code",
"source": [
"toa_col = toa_col.map(calc_ndvi)\n",
"toa_col.first()"
],
"metadata": {
"id": "ioY13FoJ9woh"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Image collection compositing"
],
"metadata": {
"id": "MYQOxalayc7x"
}
},
{
"cell_type": "code",
"source": [
"toa_max = toa_col.max()\n",
"\n",
"m.add_layer(toa_max, false_color_vis, 'TOA max')"
],
"metadata": {
"id": "OuWsqjf5An1N"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Clip image to Walla Walla basin"
],
"metadata": {
"id": "JUEdqLa8yjgH"
}
},
{
"cell_type": "code",
"source": [
"toa_max_basin = toa_max.clip(wawa_basin)\n",
"\n",
"ndvi_vis = {\n",
" 'bands': ['ndvi'],\n",
" 'min': 0,\n",
" 'max': 0.7,\n",
" 'palette': cm.get_palette('Greens')\n",
"}\n",
"m.add_layer(toa_max_basin, ndvi_vis, 'NDVI max basin')\n",
"m.add_layer(toa_max_basin, ndvi_vis, 'TOA (first)')\n",
"m.remove_ee_layer('TOA max')"
],
"metadata": {
"id": "4WEvGGShBTdB"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Zonal statistics: median max NDVI riparian vs upland"
],
"metadata": {
"id": "nl3dNcUQ1fOv"
}
},
{
"cell_type": "code",
"source": [
"toa_riparian = toa_max_basin.reduceRegion(\n",
" reducer=ee.Reducer.median(),\n",
" geometry=riparian,\n",
" scale=50\n",
")\n",
"\n",
"toa_upland = toa_max_basin.reduceRegion(\n",
" reducer=ee.Reducer.median(),\n",
" geometry=upland,\n",
" scale=200\n",
")\n",
"\n",
"display('Median riparian NDVI', toa_riparian.getNumber('ndvi'))\n",
"display('Median upland NDVI', toa_upland.getNumber('ndvi'))"
],
"metadata": {
"id": "EeBOheg8E9Sg"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"## Sampling"
],
"metadata": {
"id": "Kg1m-6HF15XO"
}
},
{
"cell_type": "code",
"source": [
"toa_max_sample = toa_max_basin.sample(\n",
" region=wawa_basin,\n",
" scale=30,\n",
" numPixels=1000\n",
")\n",
"\n",
"print_table(toa_max_sample, 'Sample')"
],
"metadata": {
"id": "vCRtN_16NTGW"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"df = ee.data.computeFeatures({\n",
" 'expression': toa_max_sample,\n",
" 'fileFormat': 'PANDAS_DATAFRAME'\n",
"})\n",
"\n",
"alt.Chart(df).mark_bar().encode(\n",
" alt.X(\"ndvi:Q\", bin=True),\n",
" y='count()',\n",
")"
],
"metadata": {
"id": "kp8DC7W34611"
},
"execution_count": null,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment