Visualising Remotely Sensed Data from Google Earth Engine in Python

DM Heli
9 min readMar 12, 2022

--

More than an interactive web application, Google Earth publicly provides a whole suite of data and tools to analyse images from satellites that are orbiting the earth.

If you’ve ever tinkered with Google Earth, you’d have probably been as amazed as I was looking at the earth from the view of satellites that have been encircling the planet for decades. In fact, the data from these satellites are neatly catalogued for us in Google Earth Engine to create our own visualisations and analyses of the particular properties and activities in the earth that we are concerned about, like rainforest cover, wildfire spread, temperatures, and ice cover. This becomes a very powerful tool in observing and analysing the manifestations of climate change or environmental degradation.

In this article, we’ll go through a code-first approach in Python to learn the basics of using satellite imagery from Google Earth Engine datasets and presenting them on static and interactive maps. The data catalog is huge, and you’ll find loads of references detailing each component of each dataset. The particular example I’m going to do is visualising the mean land surface temperature of a particular region of interest in 2021 using data from MODIS, one of the scientific instruments aboard NASA’s Terra satellite.

There are two main ways we can render satellite imagery in Python:

  • By loading a static image from Google Earth Engine datasets
  • By using a Python library called folium to create an interactive map

Google Earth Engine provides an API to load and process satellite data in distributed servers so that we don’t need to worry about the computational limits of our personal computers to process these big imagery data. On top of the API, Google Earth Engine also supports Javascript and Python SDKs, so that developers can easily integrate Google Earth images into their applications. While Javascript gets a lot more online support, the Python SDK is much more extensible because of its data manipulation capabilities.

Pre-requisite knowledge and tools

  1. Intermediate Python knowledge and programming skills
  2. Python 3 environment setup, particularly Jupyter notebook installation
  3. Basic understanding of Google Earth

It’s best to use Jupyter notebooks (or Google Colab) with Google Earth Engine Python SDK, as the images can be readily displayed on your browser.

Google Earth Engine Python SDK setup

With the assumption that you can read and write intermediate-level Python code, I’ll go ahead and just link to the Google Earth Engine Python installation page to get you started on your environment setup. Basically, you need to:

  • Install the Python client library for Google Earth Engine
  • Create Google Earth Engine credentials to authenticate to the API (free!)

Part 1: Rendering a static map

In this exercise, we’ll render a static map of the land surface temperature of the Philippines in 2021 using the MODIS Terra Land Surface Temperature dataset in Google Earth Engine.

Complete Code

Walkthrough

First, let’s identify the point on earth that we want to visualise. I’ve chosen coordinates that centre to the Philippines. We use `ee.Geometry.Point` to specify a point in the earth using a [longitude, latitude] pair.

poi = ee.Geometry.Point([122.1247, 13.2735])

More info: Footnote 1.1. Where to get location coordinates

A point alone would not be able to show us an entire country. So, we’ll need to “zoom out” of that point using a buffer, which expands the geometry by the given distance in meters (by default). In our example, let’s zoom out to a radius of 9.2 x 10⁵ meters (or 920 km) from the point of interest. You can adjust this buffer by as much as you like.

roi = poi.buffer(distance=9.2e5)

More info: Footnote 1.2. Geometry.Point buffer

Now that we’ve established the region that we want to see, let’s grab some satellite data from the Google Earth Engine datasets. In this example, I’ll use a dataset from a satellite called MODIS, which provides an Image Collection of Global Land Surface Temperature with a spatial resolution of 1 kilometre.

dataset = ee.ImageCollection("MODIS/006/MOD11A1")

dataset = dataset.select('LST_Day_1km')

More info: Footnote 1.3. Information about the MODIS dataset

More info: Footnote 1.4. Google Earth Engine Images, Features, ImageCollections, and FeatureCollections

We can filter the ImageCollection by a range of dates. Let’s say we want to get the land surface temperature of the Philippines in the year 2021. We use the ee.Filter object to define a date filter, and then pass this to the filter() function of dataset.

date_filter = ee.Filter.date('2021-01-01', '2022-01-01')

dataset = dataset.filter(date_filter)

The first date parameter is the initial date of observation (inclusive), while the second date parameter is the day after the last day of observation. This filter gives us the whole range of dates in the year 2021.

We’re still left with a bunch of images from the dataset. By default, these images are sorted by date, and they are stacked on top of each other, the latest image being at the top of the stack. This is called a mosaic. We want an image that could show us the average (or sometimes, the median) of all these images. This combination of images is called a composite, and this is one of the most useful ways we can visualise a collection of raster data over date ranges.

In this example, we’ll create the composite image of the Philippines’ 2021 Land Surface Temperature by calculating the mean of the overlapping pixels of its images.

image = dataset.mean()

image = image.multiply(0.02).add(-273.15)

The second line in the above code snippet looks like an arbitrary transformation, but fear not. There is an explanation to it by looking back at the dataset description, a portion of which is below. Under the Scale column, you’ll find the value 0.02. This means that in order to render the LST_Day_1km band in a 256x256 pixel image, we need to scale it by 0.02 (thus, image.multiply(0.02)). Next, under the Units column, notice that the temperature data is provided in Kelvin, which is not normally used in everyday conversation. We can convert this to a more familiar measurement unit like Celsius or Fahrenheit. I’ve chosen to convert it to Celsius through add(-273.15).

Bands of MOD11A1.006 Terra Land Surface Temperature and Emissivity Daily Global 1km dataset
  • More info: Footnote 1.5. How images are scaled in Google Earth Engine

The last part of the code is setting up the visualisation parameters. These specify what ranges of the temperature data we want to visualise, what colours to use, and what the size of the final image will be.

visualisation_params = {  'min': 8,  'max': 40,  'dimensions': 620,  'region': roi,  'palette': ['blue', 'yellow', 'red']}url = image.getThumbUrl(visualisation_options)Image(url=url)

Let’s put a bit more detail into the visualisation_params variable:

  • min: the minimum temperature value that we want to visualise in the region
  • max: the maximum temperature value that we want to visualise in the region
  • dimensions: the size (in pixels) of the output image
  • region: the region that we want to apply the visualisation to
  • palette: the colours that we want to use to indicate the different temperature levels

So, given these definitions, setting min: 8, max: 40 and palette: [‘blue’, ‘yellow’, ‘red’] roughly means that areas with temperatures from 8 to around 18 degrees on average will appear bluish, then as temperatures increase, they appear more yellow. When the temperatures are up to around 28 degrees, they start to appear orange (because of the mix of yellow and red), and then as temperatures increase even more until the max temperature of 40 degrees, the areas appear red. See the example of the northern part of the Philippines, wherein the mountainous areas have blue streaks as the mean temperatures there are cooler. The area encompassing Metropolitan Manila is completely red, indicating the hottest temperatures on average.

Output

Mean land surface temperature of the Philippines in 2021 showing temperature ranges from 8 degrees to 40 degrees Celsius. The bluish spots indicate the cooler temperatures in the mountainous regions; Yellow areas correspond to relatively mild temperate regions; Meanwhile, orange to red areas indicate the hottest regions throughout the year. The reddest area is, as expected, the densest city in the country — Metro Manila.

Part 2: Rendering an interactive map

In the previous exercise, we were able to render a static image of the Philippines using the MODIS Land Surface Temperature dataset. In this next part, we’ll render the same image but on an interactive map using Google Earth. To create a Google Earth interactive map, we can use a library called folium which provides the abstractions to manipulate a Google Earth satellite image and add the MODIS satellite dataset as another layer on top.

Complete Code

Walkthrough

The code for the interactive map looks very similar to the one in the previous exercise on rendering a static image. Let’s focus on the main differences.

coords = [13.2735, 122.1247]  # [lat, long]Map = folium.Map(location=coords, zoom_start=6)Map.setOptions('SATELLITE')

First, Folium accepts geographic coordinates as latitude and longitude pairs (note: latitude comes first). To load the Google Earth map, we pass the coordinates and an initial zoom value to the folium.Map object. Note that we no longer need to use a buffer to zoom out to the region of interest, since an interactive map does that for us.

Once we’ve instantiated our folium map, we can set the base map type. Here I’ve chosen to use the SATELLITE map type.

More info: Footnote 1.6. Supported map types

Skipping over to the next difference: the visualisation_params variable.

visualisation_params = {  'min': 8,  'max': 40,  'palette': ['blue', 'yellow', 'red']
}

Unlike the previous static map’s `visualisation_params`, there is no need to specify the dimensions and region properties, since we’re no longer rendering a static image of certain dimensions, and the region of interest would have to be added as a layer on top of the map. We add the layer by using the addLayer() function, which takes as arguments the image data, the visualisation parameters, and the name that we want to give to the layer.

Map.addLayer(image, visualisation_params, 'Land Surface Temperature')

Interactive maps on Google Earth typically have control buttons in addition to the zoom buttons (which appear by default). The following code adds a layer control button (to show/hide map layers), and a full screen control button to the map.

Map.setControlVisibility(layerControl=True, fullscreenControl=True)

Output

The Modis Land Surface Temperature image of the Philippines as a layer on top of the Google Earth satellite interactive map. When the code is run on Jupyter notebook, you can drag around the output area to see how the temperature data is visualised in other countries. Notice the button on the top right — this allows you to show or hide layers on the map.

Summary

In this post, we created the same map using two ways: by rendering a static image, and then by creating an interactive map. We used the Google Earth Engine API to get remotely sensed image data (particularly from the MODIS dataset) on our region of interest so that we can analyse a feature of that region aggregated over a period of time (particularly average land surface temperature in 2021). Although other datasets on the Google Earth Engine catalog have different spectral bands and different use cases, we can perform roughly same pattern of data manipulation for other types of analyses.

Footnotes and References

1.1. Where to get location coordinates

  • You can use Google Maps to quickly obtain the coordinates of a certain location (at least that’s what I usually do). Wherever you are on Google Maps, the geographic coordinates of the place at the centre of the screen appears on the address bar. You can copy these coordinates, but remember which one is latitude and which one is longitude. In Google Maps, the latitude value comes first.

1.2. Geometry.Point buffer

1.3. Information about the MODIS dataset

  • MODIS (Moderate Resolution Imaging Spectroradiometer) is an instrument aboard NASA’s Terra and Aqua Satellites, which are low-earth orbiting satellites that measure properties of land and oceans. MODIS can measure atmospheric conditions as well as photosynthetic activity, making it useful for measurements of the impact of environmental changes to the earth’s climate.
  • One of the datasets collected from MODIS is the Daily Global Land Surface Temperature and Emissivity dataset. It has a 1200km spatial resolution, meaning that each grid in an image covers 1200km of the earth’s surface.
  • Further reading about MODIS: Thanh Noi Phan & Martin Kappas (2018), “Application of MODIS Land Surface Temperature Data: a systematic literature review and analysis
  • Further reading from NASA’s article about MODIS
  • Google Earth data reference of MODIS Land Surface Temperature and Emissivity dataset

1.4. Data from Google Earth Engine can be images, collections, or features.

  • An image is any raster data (gridded/pixelated data where each pixel refers to a geographic location)
  • A feature is data about the attributes of a certain area (e.g. vegetation)
  • A collection is set of images or features

1.5. How images are scaled in Google Earth Engine

1.6. Supported map types

--

--