1. Introduction to Earth Engine
Acknowledgments
Google Earth Engine Team (EE guides)
Ujaval Gandhi (Spatial Thoughts)
Shaun R Levick (GEARS Lab)
Introduction
Google Earth Engine is a cloud-based platform that enables large-scale processing of satellite imagery to detect changes, map trends, and quantify differences on the Earth’s surface. This course covers a range of topics in Earth Engine to give you practical skills to master the platform and implement your remote sensing projects.
Objective
The main aim of this course is to familiarize you with the many possibilities you have with Earth Engine. By its very nature, this course can only introduce the basic elements of this geospatial processing service. We hope that it sparks your enthusiasm to go the remaining mile.
The aim of today's session is to give you an introduction to the Google Earth Engine processing environment and its basic elements. By the end of this day you will know the main pillars that make up Earth Engine. We strongly recommend that you play around with the following code snippets. By default, you can't break anything. Enjoy the ride and have fun experimenting.
Prerequisites
Completion of this block course requires use of the Google Chrome browser and a Google Earth Engine account. This account is linked with Google Cloud and users must create a Google Cloud Project to use the service. A step-by-step guide for signing-up for a GEE account with a cloud-project can be found here:
Once registered you can access the Earth Engine coding environment here:
https://code.earthengine.google.com
Google Earth Engine uses the JavaScript programming language. We will cover the basics of this language during this course. If you would like more detail you can read through the introduction provided here:
Learning Resources
Code repository (this course)
https://code.earthengine.google.com/?accept_repo=users/wulf/GEO717
Documentation
Discussion Group
Google Earth Engine Developers
Online-Book
Could-Based Remote Sensing with Google Earth Engine: Fundermentals and Applications
Google earth engine tutorials (same book as above with easy web access)
User summits
2017 user summit in Mountain View
2016 user summit in Mountain View
Google Earth Outreach
https://earthoutreachonair.withgoogle.com/#earthengine
Github
https://github.com/google/earthengine-api
https://github.com/gee-community
https://github.com/giswqs/Awesome-GEE
Python
EE Courses
Data resources
The Earth Engine code editor
Editor Panel
The Code Editor is where you type, debug, run and manage your Javascript code
Right Panel
Console tab for printing output.
Inspector tab for querying map results.
Tasks tab for managing long running tasks.
Left Panel
Scripts tab for managing your programming scripts.
Docs tab for accessing documentation of Earth Engine objects and methods, as well as a few specific to the Code Editor application
Assets tab for managing assets that you upload.
Interactive Map
For visualizing map layer output
Search Bar
For finding datasets and places of interest
Help Menu
User guide: reference documentation
Developers Q&A site: link to EE's gis.stackexchange.com site
Developers disscussion group: Google group for discussing Earth Engine
Shortcuts: Keyboard shortcuts for the Code Editor
Feature Tour: overview of the Code Editor
Earth Engine basics
Printing
Printing out information to the console is a basic task for getting information about an object, displaying the numeric result of a computation, displaying object metadata or helping with debugging. The iconic ‘Ay caramba!’ example in the Code Editor is:
Open in Code Editor or copy this line into the Code Editor and click Run. Note that the output is displayed in the Console tab, on the right of the Code Editor.
Basic data types
The two most fundamental geographic data structures in Earth Engine are Image
and Feature
corresponding to raster and vector data types, respectively. Images are composed of bands and a dictionary of properties. Features are composed of a Geometry
and a dictionary of properties. A stack of images (e.g. an image time series) is handled by an ImageCollection
. A collection of features is handled by a FeatureCollection
. Other fundamental data structures in Earth Engine include Dictionary
, List
, Array
, Date
, Number
and String
.
Strings
Using variables to store objects and primitives helps code readability. For example, a variable that stores a string object is defined by single '
or double "
quotes (but don't mix them), with single quotes preferred. Make a new string and store it in a variable called greetString
:
Open in Code Editor (all data type examples)
Numbers
Note that variables are defined with the keyword var
. Variables can also store numbers:
Lists
Define lists with square brackets []
. A list of numbers, for example:
Lists can also store strings or other objects. For example:
Objects
Objects in JavaScript are dictionaries of key: value
pairs. Make an object (or dictionary) using curly brackets {}
, for example:
Note that you can get a value from a dictionary by supplying the key. This example shows you how to do that for JavaScript objects. Later you'll learn how to do it for dictionaries that are on the Earth Engine server.
Playtime
These are the Top 3 happiest countries (and their scores) in the world (2024):
Finland (7.74)
Denmark (7.58)
Iceland (7.53)
Task: (1) Create a dictionary named 'happyCountries'. The dictionary should feature the countries as keys and their scores as value. (2) Print the dictionary.
Saving scripts
When you modify any script from the course repository, you may want to save a copy for yourself. If you try to click the Save button, you will get an error message like below
This message appears because the shared course repository is a Read-only repository. You can click Yes to save a copy in your repository. If this is the first time you are using Earth Engine, you will be prompted to choose the name of your home folder. Choose the name carefully, as it cannot be changed once created.
JavaScript Syntax
All the JavaScript you need to know (almost)
Comments
Open in Code Editor (all Syntax examples)
Quotes
Semi-colon
Statements can but don't need to end with a semi-colon (no complains)
Parentheses
Parentheses are used to pass parameters to functions.
Square brackets
Square brackets are used for selecting items within a list.
Curly brackets
Curly brackets (or braces) can be used to define dictionaries (key:value pairs)
Errors
Playtime
Task: Get to know your enemy. Generate errors by using (a) different quotes in a list and (b) missing brackets and debug them.
ee.Objects
To ease processing at Google' cloud servers, Earth Engine wants you to put JavaScript objects and primitives into Earth Engine containers.
Declaring variables
A container object (usually in the form ee.SomeVariableType
) is used to wrap a native JavaScript object so that Google's servers can perform operations on it.
Strings
Think of ee.Thing
as a container for a thing that exists on the server. In this example, the string is defined first, then put into the container.
Open in Code Editor (all ee.Objects examples)
Although the first argument to print()
is just a string on the client, the second argument is actually sent to the server to be evaluated, then sent back.
Numbers
Arrays
Lists
Dictionaries
Casting
Sometimes, Earth Engine doesn't know the type of an object that gets returned from a method. You, as the programmer, know that the object and need to cast it into the correct container.
Task: What is the correct result of this operation?
Dates
Date objects are the way Earth Engine represents time. As in the previous examples, it is important to distinguish between a JavaScript Date
object and an Earth Engine ee.Date
object. Construct an ee.Date
from a string, from a JavaScript Date
, or using static methods provided by the ee.Date
class. (See the Date section in the Docs tab for details). This example illustrates the construction of dates from strings or a JavaScript date representing milliseconds since midnight on January 1, 1970:
Dates are useful for filtering collections, specifically as arguments to the filterDate()
method.
Playtime
Task 1: Numbers
Generate a list of numbers from 1 to 10
Extract the number 4 from that list and define it a new variable
Add the number 7 to it by using the function ".add()"
Task 2: Dictionary
Read in the following data: var data = {'city': 'Marseille', 'population': 860000, 'elevation': 36}
Print the name of the city using the ".get()" function.
Task 3: Dates
Define your birthday as an "ee.Date".
Calculate your current age in days using the ".difference()" function.
Add ten years to your birthday using the function ".advance()".
Functions
A function is a set of instructions to perform a specific task. Define a function with the function
keyword. Function names start with a letter and have a pair of parentheses at the end. Functions often take parameters which tell the function what to do. These parameters go inside the parentheses ()
. The set of statements making up the function go inside curly brackets. The return
keyword indicates what the function output is. There are several ways to declare a function, but here we'll use something like this:
Let's consider the lines one by one. The first line creates a new function and assigns it to the variable myFunction
. This variable could have been named anything. It defines how to call the function later. The terms in the parentheses after the function name (i.e. parameter1, parameter2, parameter3) are the parameter names and could have been named anything as well, though it's good practice to give them unique names that are different from the code outside the function. Whatever you name them, these are the names that function will use to refer to the values that are passed into the function when it is called. The value of a parameter once it's been passed into a function is called an argument. Although functions can use variables declared outside the function (global variables), function arguments are not visible outside the function. Functions can take as many parameters as you need, even zero. Here's a simple example of a function that just returns its argument with some text:
Open in Code Editor
Here is another simple example using numbers.
Calling a function
Playtime
Task: Define one function that states your name and calculates your favourite number.
Mapping a function
Mapping a function over a collection applies the function to every element in the collection.
Here is a simple example:
Playtime
Task: Define a function that computes the squares (".pow(2)") and map it on a list of number from 1 to 10.
Image
Okily Dokily! Let's get started with remote sensing images. Any raster data are represented as Image
objects in Earth Engine. Images are composed of one or more bands and each band has its own name, data type, scale, mask and projection. Each image has metadata stored as a set of properties. An easy way to look into these properties is to print the image.
Printing
The following example prints the metadata of a Landsat 8 image:
Inspect the output in the console to see metadata available for Landsat images.
Playtime
Task: Let's find out at which date and time the image was acquired.
to retrieve image properties use: var property_name = image.get('property')
to convert the time from milliseconds to a common date format, use the ee.Date() container and print it.
Be aware that the default time zone is UTC
Image Visualization
The following illustrates the use of parameters to style a Landsat 8 image as a false-color composite:
Playtime
Tasks:
Display the image as a 'natural false color image' using the bands B7 (SWIR2), B5 (NIR) and B4 (red).
Adjust the maximim reflectance of each band to B7 = 0.25, B5 = 0.35, B4 = 0.25.
Use the command "Map.setCenter()" to define the display location (lon: 4.99, lat: 43.43) and zoom level (11).
Image Math
Image math can be performed using operators like add()
and subtract()
, but for complex computations with more than a couple of terms, the expression()
function provides a good alternative.
Operators
Math operators perform basic arithmetic operations on image bands. They take two inputs: either two images or one image and a constant term, which is interpreted as a single-band constant image with no masked pixels. Operations are performed per pixel for each band.
As a simple example, consider the task of calculating the Normalized Difference Vegetation Index (NDVI) using Landsat imagery, where add()
, subtract()
, and divide()
operators are used:
Note: the normalized difference operation is available as a shortcut method: normalizedDifference()
.
Playtime
Task: Perform the normalizedDifference() operation to calculate the NDWI (normalized difference water index, formula below) for the same scene.
Expressions
Excellent! To implement more complex mathematical expressions, consider using image.expression()
, which parses a text representation of a math operation. The following example uses expression()
to compute the Enhanced Vegetation Index (EVI):
Observe that the first argument to expression()
is the textual representation of the math operation, the second argument is a dictionary where the keys are variable names used in the expression and the values are the image bands to which the variables should be mapped.
Playtime
Task: Perform an image.expression() operation to calculate the Bare Soil Index (BSI, see formula below):
Image Operations
ee.Image
objects have a set of relational, conditional, and boolean methods for constructing decision-making expressions. The results of these methods are useful for limiting analysis to certain pixels or regions through masking, developing classified maps, and value reassignment.
Relational and Boolean Operations
Relational methods include:eq()
(meaning 'equal' or '=') ,gt()
(meaning 'greater than' or '>') , gte()
, (meaning 'greater than or equal' or '>=') ,lt()
, (meaning 'less than' or '<') and lte()
(meaning 'less than or equal' or '<=') .
Boolean methods include: and()
,or()
, and not()
To perform per-pixel comparisons between images, use relational operators. To extract urbanized areas in an image, this example uses relational operators to threshold spectral indices, combining the thresholds with the and operator:
Playtime
Task:
".select()" the thermal band 'B10' from the image, threshold it at 300 K, and mask areas that are 'no water'.
Display the water in blue on top of the natural false colour image (B7, B5, B2).
Conditional Operations
Another way to implement conditional operations on images is with the where()
operator. Consider the need to replace masked pixels with some other data. In the following example, cloudy pixels are replaced by pixels from a cloud-free image using where()
:
There are a couple of things in this code that are worth mentioning in detail. First, the select()
function is useful for extracting the bands of interest from an image. Here, we select only the band we care about: cloud
. The next thing is the logical operator gt()
which stands for "greater thean." We use gt(10)
to create a binary image in which all the pixels that exceed the value of 10 (those that are clouds) get replaced by pixel values of the less cloudy image.
Playtime
Task: Replace the snow covered pixels from one image with the snow free pixel from the other image
Threshold the NDSI at 0.35 to identify snow covered pixel
Seperate water from snow using the NIR reflectance at 0.2
Replace the snow pixels using the ".where()" function
Masking
Masking pixels in an image makes those pixels transparent and excludes them from analysis. Each pixel in each band of an image has a mask. Those with a mask value of 0 or below will be transparent. Those with a mask of any value above 0 will be rendered. The mask of an image is set using a call like image1.mask(image2)
. This call takes the values of image2
and makes them the mask of image1
. Any pixels in image2
that have the value 0 will be made transparent in image1
.
The command .updateMask()
updates an image's mask at all positions where the existing mask is not zero. In other words, if mask == 1 the data is retained, if mask == 0 the data is masked (set to transparent, NaN). The output image retains the metadata and footprint of the input image. The same operations apply to the command .mask()
The command .selfMask()
updates an image's mask at all positions where the existing mask is not zero using the value of the image as the new mask value. In other words, all pixel with the image value zero get masked (set to transparent).
The command .unmask()
replaces mask and value of the input image with the mask and value of another image at all positions where the input mask is zero. If only the input image gets unmasked, all masked pixel are set to zero.
Playtime
Task: Mask a Landsat 7 image based on its VZA-band (viewing zenith angle) to exclude all pixel affected by its SLC (scan line corrector) failure.
Morphology
Earth Engine implements morphological operations as focal operations, specifically focal_max()
, focal_min()
, focal_median()
, and focal_mode()
instance methods in the Image
class. The morphological operators are useful for performing operations such as erosion, dilation, opening and closing. For example, to perform an opening operation, use focal_min()
followed by focal_max()
:
Note that in the previous example, a kernel argument is provided to the morphological operator. The pixels covered by non-zero elements of the kernel are used in the computation. The iterations argument indicates how many times to apply the operator.
Playtime
Task: Let's go to a happy place (Finland) and buffer clouds. Calculate the simpleCloudScore, threshold the score at 50 and perform an opening operation to eliminate false positives and buffer the cloud margins. Mask the image based on your buffered cloud mask.
ImageCollection
An ImageCollection
is a stack or sequence of images. An ImageCollection
can be loaded by pasting an Earth Engine asset ID into the ImageCollection
constructor. You can find ImageCollection
IDs in the data catalog. For example, to load the Sentinel-2 surface reflectance collection:
For each dataset you will find an "Explore with Earth Engine" section, which provides a code snippet to load and visualise the collection. This snippet is a great starting point for your work with this dataset.
ImageCollection overview
Filtering
This collection contains every Sentinel-2 image in the public catalog. There are a lot. Usually you want to filter the collection to include only relevant data that supports your purpose. Consider dates, spatial extent, quality, and other properties specific to a given dataset.
For instance, filter a Sentinel-2 surface reflectance collection by a single date range, a region of interest, or an image property.
Sorting
Sort a collection by time to ensure proper chronological sequence, or order by a property of your choice. By default, the visualization frame series is sorted in natural order of the collection. The arrangement of the series can be altered using the sort
collection method, whereby an Image
property is selected for sorting in either ascending or descending order. For example, to sort by time of observation, use the ubiquitous system:time_start
property.
Or perhaps the order should be defined by increasing cloudiness:
Task: Filter the Sentinel-2 image collection to display the least-cloudy image of your hometown. Use the function ".first()" to select the first image of a collection.
Information and Metadata
As with Images, there are a variety of ways to get information about an ImageCollection
. The collection can be printed directly to the console, but the console printout is limited to 5000 elements. Collections larger than 5000 images will need to be filtered before printing. Printing a large collection will be correspondingly slower. The following example shows various ways of getting information about image collections programmatically:
Task: Provide the date for least-cloudy Sentinel-2 image with the lowest solar zenith angle (least amount of shadows) obtained in Istanbul.
Reducing an ImageCollection
To composite images in an ImageCollection
, use imageCollection.reduce()
. This will composite all the images in the collection to a single image representing, for example, the min, max, mean or standard deviation of the images. (See the Reducers section for more information about reducers). For example, to create a median value image from a collection:
At each location in the output image, in each band, the pixel value is the median of all unmasked pixels in the input imagery (the images in the collection). In the previous example, median()
is a convenience method for the following call:
Note that the band names differ as a result of using reduce()
instead of the convenience method. Specifically, the names of the reducer have been appended to the band names.
Playtime
Task: Use the entire Landsat 8 Collection 2 (TOA) from 2014 to 2021 at path 172 and row 72 as your input dataset.
Print the number of images from this collection.
Compute and display the median and the mean of the collection.
Compute and display the ratio image between the sum of all optical mean bands and the sum of all optical median bands.
Mapping over an ImageCollection
To apply a function to every Image
in an ImageCollection
use imageCollection.map()
. The only argument to map()
is a function which takes one parameter: an ee.Image
. For example, the following code adds a timestamp band to every image in the collection:
Note that in the predefined function, the metadata()
method is used to create a new Image
from the value of a property. Having that time band is useful for the linear modelling of change and for making composites.
Even more useful is to apply a cloud filter to an entire ImageCollection. Let's see the example below:
Note the marked difference in image quality between the 'normal' median and the 'cloud-free' median image. Mapping a function over an ImageCollection is a powerful tool, we will use a lot.
Playtime
Task: Write and map a function that adds a NDVI-band to the ImageCollection (use the command ".addBands()") and filters clouds. Display the cloud-filtered median of the NDVI.
Compositing and Mosaicking
In general, compositing refers to the process of combining spatially overlapping images into a single image based on an aggregation function. Mosaicking refers to the process of spatially assembling image datasets to produce a spatially continuous image. In Earth Engine, these terms are used interchangeably, though both compositing and mosaicking are supported.
Consider the need to mosaic two, or more, neighboring Landsat scenes as these cover your study area. The following example demonstrates that using imageCollection.mosaic()
:
Note that there is significant overlap in the Landsat tiles in the previous example. The mosaic()
method composites overlapping images according to their order in the collection (last on top). To control the source of pixels in a mosaic (or a composite), you can make use of imageCollection.qualityMosaic()
to maximizes an arbitrary band in the collection. The qualityMosaic()
method sets each pixel in the composite based on which image in the collection has a maximum value for the specified band. For example, the following code demonstrates making a greenest pixel composite and a recent value composite:
Playtime
Task: Generate a "whitest pixel composite" by maximizing snow cover using the NDSI ( .normalizedDifference(['Green', 'SWIR1']) ).
Geometry
Earth Engine handles vector data with the Geometry
type. The GeoJSON spec describes in detail the type of geometries supported by Earth Engine, including Point
(a list of coordinates in some projection), LineString
(a list of points), LinearRing
(a closed LineString
), and Polygon
(a list of LinearRing
s where the first is a shell and subsequent rings are holes). Earth Engine also supports MultiPoint
, MultiLineString
, and MultiPolygon
. The GeoJSON GeometryCollection is also supported, although it has the name MultiGeometry
within Earth Engine.
Creating Geometries
Using any of the drawing tools will automatically create a new geometry layer and add an import for that layer to the Imports section. To add geometries to a new layer, hover on the Geometry Imports in the map display and click the +new layer link. You can also toggle visibility of the geometries from the Geometry Imports section.
To configure the way geometries are imported to your script, click the settings icon next to the layer in the Geometry Imports section on the map or in the Imports section of the code editor. The geometry layer settings tool will be displayed in a dialog box which should look something like the Figure below. Note that you can import the drawn shapes as geometries, features or feature collections. The geometry import settings also allow you to change the color with which the layer is displayed, add properties to the layer (if it is imported as a Feature
or FeatureCollection
) or rename the layer.
Finally, to prevent geometries in a layer from being edited, you can lock the layer by pressing the "lock_open" icon next to the layer. This will prevent adding, deleting, or editing any geometries on the layer. To unlock the layer again, press the "lock" icon.
Playtime
Test the geometry tools, by playing with them.
Edit layer properties (e.g. rename them, adjust the colors, and lock the editing mode).
Adjust the geometries (e.g. move them, change the extent, delete them)
To create a Geometry
programmatically, provide the constructor with the proper list(s) of coordinates. For example:
To display a geometry just by its outline without any fill color, you need to convert the geometry into an image and paint its margins.
Playtime
Task: Create a circular geometry around Rio de Janeiro by buffering a point with a 100 km radius. Display the outline of the geometry.
Geometry Information
To view information about a geometry, print it. To access the information programmatically, Earth Engine provides several methods. For example, to get information about a polygon, use:
Observe that the perimeter (or length) of a geometry is returned in meters and the area is returned in square meters unless a projection is specified. By default, the computation is performed on the WGS84 spheroid and the result is computed in meters or square meters.
Playtime
Task: Which country has the most/least compact shape?
A features compactness can be measured by using the Polsby-Popper test. First you need to map functions that add the features area and perimeter as a property.
Geometric Operations
Earth Engine supports a wide variety of operations on Geometry
objects. These include operations on individual geometries such as computing a buffer, centroid, bounding box, perimeter, convex hull, etc. For example:
Observe from the previous example that the buffer distance is specified in meters.
Supported geometric operations also include relational computations between geometries such as intersection, union, difference, distance, contains, etc.
In these examples, note that that maxError
parameter is set to one meter for the geometry operations. The maxError
is the maximum allowable error, in meters, from transformations (such as projection or reprojection) that may alter the geometry. If one of the geometries is in a different projection from the other, Earth Engine will do the computation in a spherical coordinate system, with a projection precision given by maxError
. You can also specify a specific projection in which to do the computation, if necessary.
FeatureCollection
Features
A Feature
in Earth Engine is defined as a GeoJSON Feature. Specifically, a Feature
is an object with a geometry
property storing a Geometry
object (or null) and a properties
property storing a dictionary of other properties.
To create a Feature
, provide the constructor with a Geometry
and (optionally) a dictionary of other properties. For example:
In the previous example, note that properties can be set with either a key: value pair, or with a dictionary as a JavaScript literal. Also note that feature.set()
overwrites existing properties.
Playtime
Task: Define a feature for your hometown (place of birth) and set the properties 'name', 'population' and 'country'. Calculate its distance to Campus Irchel.
Collections
Groups of related features can be combined into a FeatureCollection
, to enable additional operations on the entire set such as filtering, sorting and rendering. Besides just simple features (geometry + properties), feature collections can also contain other collections.
One way to create a FeatureCollection
is to provide the constructor with a list of features. The features do not need to have the same geometry type or the same properties. For example
Earth Engine hosts a variety of table datasets. To load a table dataset, provide the table ID to the FeatureCollection
constructor. For example, to load TIGER roads data:
To get a collection of random points in a specified region, you can use:
Visualisation
As with images, geometries and features, feature collections can be added to the map directly with Map.addLayer()
. The default visualisation will display the vectors with solid black lines and semi-opaque black fill. To render the vectors in color, specify the color
parameter. For more control over how a FeatureCollection
is displayed, use image.paint()
with the FeatureCollection
as an argument. Note that the empty image into which you paint the features needs to be cast prior to painting. Both the color and width with which the boundaries are drawn can be set with properties.
Filtering
Methods for getting information from feature collection metadata are the same as those for image collections. Also, filtering a FeatureCollection
is analogous to filtering an ImageCollection
. (See the Filtering an ImageCollection section). There are the featureCollection.filterDate()
, and featureCollection.filterBounds()
convenience methods and the featureCollection.filter()
method for use with any applicable ee.Filter
.
Playtime
Task: Filter the global river dataset for rivers in India with and upstream watershed area ('UPLAND_SKM') larger than 10 km^2.
Mapping
To apply the same operation to every Feature
in a FeatureCollection
, use featureCollection.map()
. For example, to add another area attribute to every feature in a watersheds FeatureCollection
and to generate an entirely new FeatureCollection
, use:
In the previous example, note that a new property is set based on a computation with the feature’s geometry. Properties can also be set using a computation involving existing properties. Note further that all selected properties are propagated to the features in the new collection.
Reducing
Which is the wettest or driest country in the world?
To aggregate data in the properties of a FeatureCollection
, use featureCollection.reduceColumns()
.
Playtime
Task: Which is the windiest / calmest country on Earth?
Reducer
Reducers are the way to aggregate data over time, space, bands, arrays and other data structures in Earth Engine. The ee.Reducer
class specifies how data is aggregated. The reducers in this class can specify a simple statistic to use for the aggregation (e.g. minimum, maximum, mean, median, standard deviation, etc.), or a more complex summary of the input data (e.g. histogram, linear regression, list). Reductions may occur over time (imageCollection.reduce()
), space (image.reduceRegion()
, image.reduceNeighborhood()
), bands (image.reduce()
), or the attribute space of a FeatureCollection
(featureCollection.reduceColumns()
or FeatureCollection
methods that start with aggregate_
).
Reducers take an input dataset and produce a single output. When a single input reducer is applied to a multi-band image, Earth Engine automatically replicates the reducer and applies it separately to each band. As a result, the output image has the same number of bands as the input image; each band in the output is the reduction of pixels from the corresponding band in the input data. Some reducers take tuples of input datasets. These reducers will not be automatically replicated for each band. For example, ee.Reducer.LinearRegression()
takes multiple predictor datasets (representing independent variables in the regression) in a particular order.
ImageCollection Reductions
Consider the example of needing to take the median over a time series of images represented by an ImageCollection
. To reduce an ImageCollection
, use imageCollection.reduce()
. This reduces the collection of images to an individual image as illustrated in Figure below. Specifically, the output is computed pixel-wise, such that each pixel in the output is composed of the median value of all the images in the collection at that location. To get other statistics, such as mean, sum, variance, an arbitrary percentile, etc., the appropriate reducer should be selected and applied. For basic statistics like min, max, mean, etc., ImageCollection
has shortcut methods like min()
, max()
, mean()
, etc. They function in exactly the same way as calling reduce()
, except the resultant band names will not have the name of the reducer appended.
For an example of reducing an ImageCollection
, consider a collection of Landsat 8 images, filtered for cloud cover.
Image Reductions
To reduce an Image
, use image.reduce()
. Reducing an image functions in an analogous way to imageCollection.reduce()
, except the bands of the image are input to the reducer rather than the images in the collection. The output is also an image with number of bands equal to number of reducer outputs. For example:
Playtime
Task: Provide the mean annual cloud probability for Zurich.
Statistics of an Image Region
To get statistics of pixel values in a region of an ee.Image
, use image.reduceRegion()
. This reduces all the pixels in the region(s) to a statistic or other compact representation of the pixel data in the region (e.g. histogram). The region is represented as a Geometry
, which might be a polygon, containing many pixels, or it might be a single point, in which case there will only be one pixel in the region. In either case, as illustrated in the Figure below, the output is a statistic derived from the pixels in the region.
For an example of getting pixel statistics in a region of an image using reduceRegion()
, consider finding the mean spectral values of a 5-year Landsat composite within the boundaries of the Sierra Nevada Coniferous Forest
Note that in this example the reduction is specified by providing the reducer
(ee.Reducer.mean()
), the geometry
(Aletsch.first().geometry()
), the scale
(30 meters) and maxPixels
for the maximum number of pixels to input to the reducer. A scale should always be specified in reduceRegion()
calls. See this page for more information about how Earth Engine handles scale.
Area calculation
To calculate the area covered by raster images, you can also use image.reduceRegion(). You can calculate areas for any geometry using the .area() function. You can calculate the area within a geometry covered by a raster image using the pixelArea() function. See the example below for the Aletsch Glacier.
Statistics of Image Regions
To get image statistics in multiple regions stored in a FeatureCollection
, you can use image.reduceRegions()
to reduce multiple regions at once. The input to reduceRegions()
is an Image
and a FeatureCollection
. The output is another FeatureCollection
with the reduceRegions()
output set as properties on each Feature
. In this example, means of the Landsat 7 annual composite NDVI in each feature geometry will be added as properties to the input features:
Linear Regressions
Earth Engine has several methods for performing linear regression using reducers: The simplest linear regression reducer is linearFit()
which computes the least squares estimate of a linear function of one variable with a constant term. For a more flexible approach to linear modelling, use one of the linear regression reducers which allow for a variable number of independent and dependent variables. linearRegression()
implements ordinary least squares regression(OLS). robustLinearRegression()
uses a cost function based on regression residuals to iteratively de-weight outliers in the data (O’Leary, 1990). ridgeRegression()
does linear regression with L2 regularization.
Regression analysis with these methods is suitable for reducing ee.ImageCollection
, ee.Image
, ee.FeatureCollection
, and ee.List
objects. The following examples demonstrate an application for each. Note that linearRegression()
, robustLinearRegression()
, and ridgeRegression()
all have the same input and output structures, but linearFit()
expects a two-band input (X followed by Y) and ridgeRegression()
has an additional parameter (lambda
, optional) and output (pValue
).
linearFit()
The data should be set up as a two-band input image, where the first band is the independent variable and the second band is the dependent variable. The following example shows the estimation of the linear trend of climate reanalysis data (ERA5-Land) for air temperatures over the last decades. The dependent variable is air-temperature and the independent variable is time (years), added prior to calling linearFit()
:
Observe that the output contains two bands, the ‘offset’ (intercept) and the ‘scale’ ('scale' in this context refers to the slope of the line and is not to be confused with the scale parameter input to many reducers, which is the spatial scale). The scale is given in two different colour ramps. Look at the range of values to interpret the colours accordingly. A value of 0.08 refers to 0.08°C warming per year. Over four decades, this equates to 3.6°C of warming.
Playtime
Task 1: Use the same 'ECMWF/ERA5_LAND/DAILY_AGGR' dataset to analyse the global precipitations trends since 1980..
Task 2: Use the 'MODIS/006/MOD13A1' (16-day vegetation indices) dataset to analyse the global vegetation trends by the EVI since 2000.
linearRegression()
For example, suppose there are two dependent variables: temperature and precipitation, and two independent variables: a constant and time. The collection is identical to the previous example, but the constant band must be manually added prior to the reduction. The first two bands of the input are the ‘X’ (independent, explanatory) variables and the next two bands are the ‘Y’ (dependent, response) variables. In this example, first get the regression coefficients, then flatten the array image to extract the bands of interest:
Inspect the results to discover that linearRegression()
output is equivalent to the coefficients estimated by the linearFit()
reducer, though the linearRegression()
output also has coefficients for the other dependent variable, total_precipitation_sum
. Robust linear regression coefficients are different from the OLS estimates. The example compares the coefficients from the different regression methods at a specific point.
This simple 1-dimensional example highlights the difference between the linear regression and the robust linear regression.
Charts
The Earth Engine JavaScript Code Editor seamlessly integrates with Google Charts for convenient tabular data visualization via ui.Chart
functions. Charts can be displayed interactively in the Code Editor console, ui.Panel
widgets, and in stand-alone browser tabs.
Chart overview
A variety of chart types can be produced; for example: scatter, line, bar, pie, and histogram. Specifically, any chart type that is available in the Google Charts corechart package can be generated. Use the ui.Chart.setChartType()
method to set chart type. Each page linked to in the Earth Engine object charts and DataTable
charts sections include examples for generating several chart types.
Interactivity
Charts are interactive by default. Hover over points, lines, bars, etc. to see respective x, y, and series values. Axis zooming and panning are optionally permitted by activating a chart's "explorer" functionality.
Styling
Google Charts are highly customizable via styling properties. Use the ui.Chart.setOptions()
method to set chart style properties. See the Chart Styling guide for full details.
Limitations
ui.Chart
functions will only render 5,000 features. If your FeatureCollection
, ImageCollection
, Array
or List
has more elements, consider ways you might limit the data. If you have a long time series with a high cadence rate, try using a shorter time period, temporal sampling, or generate temporal composites.
DataTable Charts
The ui.Chart
function is essentially a 2-D table with rows that represent observations and columns that represent observation attributes. It is a good option when a high degree of chart customization is required.
Suppose you have a small amount of static data you want to display to a chart. Use either the JavaScript array or object specifications to construct an input to pass to the ui.Chart
function. Here, the top five asian populations from a 2022 census are encoded as a JavaScript array with column header objects that define column properties.
Image Charts
The ui.Chart.image
module contains a set of functions for reducing Image
objects by region(s) and rendering charts from the results. The choice of function dictates the arrangement of data in the chart, i.e., what defines x- and y-axis values and what defines the series. See the respective website on Image Charts to get a more comprehensive overview of chart functions and respective examples. We will focus on two chart functions: ui.Chart.image.regions
and ui.Chart.image.histogram
ui.Chart.image.regions
The ui.Chart.image.regions
function accepts a list that allows you to plot data from multiple regions of your image. The following example displays a spectral profiler.
Playtime
ui.Chart.image.histogram
Imagine you want to identify a suitable threshold for the normalized difference water index (NDWI) to distinguish water from land. Displaying the histogram of the respetive index image is a suitable way to identify the target region.
Playtime
Task: Load the DEM dataset "USGS/SRTMGL1_003", clip it to the image geometry (see given example) and display its histogram. Adjust the number of buckets/bins to 300.
ImageCollection Charts
The ui.Chart.image
module contains a set of functions for rendering charts from the results of spatiotemporal reduction of images within an ImageCollection
. The choice of function dictates the arrangement of data in the chart, i.e., what defines x- and y-axis values and what defines the series. Use the function descriptions and examples to determine the best function for your purpose.
In this following example we will compare two charts on the same dataset.
Use ui.Chart.image.doySeriesByRegion
to display a single image band day-of-year time series for multiple regions, where each distinct region is presented as a unique series. It is useful for comparing annual single-band time series among regions. For instance, in this example, annual MODIS-derived EVI profiles for three forest regions are plotted, providing a convenient comparison of EVI response by region. Note that intra-annual observations occurring on the same day-of-year are reduced by their mean.
Use ui.Chart.image.series
to display an image time series for a given region; each image band is presented as a unique series. It is useful for comparing the time series of individual image bands. Here, a MODIS image collection with bands representing NDVI and EVI vegetation indices are plotted. The date of every image observation is included along the x-axis, while the mean reduction of pixels intersecting the forest ecoregion defines the y-axis.
Importing & exporting data
Importing and Managing Assets
To upload and manage geospatial datasets, use the Asset Manager in the Code Editor. The Asset Manager is on the Assets tab at the left side of the Code Editor (Figure below. See Importing Raster Data for instructions on uploading raster (image) data and Importing Table Data for instructions on uploading table data. Your assets are initially private, but may be shared with others. See the Sharing Assets section for details.
Exporting Data
You can export images, map tiles, tables and video from Earth Engine. Most commonly, vector data are exported as a CSV
or a Shapefile
, while Rasters are exported as GeoTIFF
files. The exports can be sent to your Google Drive account, to Google Cloud Storage (a fee-based service) or to a new Earth Engine asset.
Exporting raster data to Google Drive
To export an image to your Drive account, use Export.image.toDrive()
. For example, to export our previously defined Landsat median image of Scotland, define the export parameters, then call Export.image.toDrive()
:
Exporting vector data to Google Drive
You can export a FeatureCollection
as CSV, SHP (shapefile), GeoJSON, KML, KMZ or TFRecord using Export.table
. The FeatureCollection
may represent vectors or simply a table of data. In the latter case, the features in the collection will have null geometry.
To export a FeatureCollection
to your Drive account, use Export.table.toDrive()
. For example:
Note that the output format is specified as SHP to handle geographic data. To export just a table of data, without any geographic information, export features with null geometry in CSV format. The following demonstrates using Export.table.toDrive()
to get the results of a potentially long running reduction:
By now you have learned quite a bit about the possibilities of the Earth Engine. In the next chapter we will focus more on time series analysis.
Last updated