Chapter 4. Geospatial Analytics in the Cloud: Google Earth Engine and Other Tools

How do you access geospatial data? Although data professionals with enterprise accounts may not think about the limitations of personal computing and relying on open source data, the rest of us often work within limits. Geospatial analysis in the cloud has narrowed the divide, since that means we no longer need to store large volumes of data locally. Never before has the general public had open source access to geospatial data on such a global scale. This chapter will show you where to find data for exploration and learning.

Space programs in the US and around the world have gathered data from satellites and sensors for decades, but only recently have we had the capacity to manipulate that data in real time for analysis. The USGS hosts EarthExplorer (Landsat), and the Copernicus Open Access Hub provides data from European Space Agency (ESA) Sentinel satellites. Landsat high-resolution satellite images enable us to evaluate and measure environmental change, understand the impact of climate science and agricultural practices, and respond to natural disasters across time and space, to name a few examples. The advent of free satellite images has enabled decision makers from economically challenged areas across the world to bring insights into view and focus on solutions.

Spatial analysis includes methods and tools applied to location data, in which the results vary based on the location or frame analyzing the object. It is essentially “location-specific” analysis. This can be as simple as locating the nearest subway station or asking how many green spaces or parks are in a community, or as complex as revealing patterns in transportation accessibility or health outcomes. Spatial algorithms are a method of solving a problem by listing and executing sequential instructions integrated with geographic properties, used for analysis, modeling, and prediction.

GIS solve spatial problems that rely on location information like latitude, longitude, and projection. Spatial information answers “where” questions: where on the Earth’s surface did something occur?

Imagine, for example, stepping out of your hotel on 41st and Madison Avenue in Manhattan. You search in your mapping app for where you might purchase a coat, since the weather is dramatically colder than you anticipated. Instantly, the locations of apparel stores populate your screen.

Or on the marketing side, say you work for an outdoor provision company, producing top-of-the-line outerwear for the discerning customer. You could use geospatial information to answer questions like: Where do your potential customers live, visit, or travel? Would a potential retail location nearby be a profitable marketing decision? How far would potential customers travel? What is the mean income within each of the locations you are considering? These where components exist in retail and commercial environments, the military, climate science, and health care, to name a few examples.

Attributes are another important component of spatially referenced data. Spatial attributes are bounded in space; these could include a community boundary or infrastructure, such as a roadway or metro station, usually represented by a polygon. Spatially referenced data can also have nonspatial attributes, such as the income of residents in a certain location, and can provide context for the location intelligence.

The I in GIS is increasingly being stored in the cloud. Today your laptop can access petabytes of information made available by geospatial analytics processing services in the cloud. This chapter will explore one of those services: Google Earth Engine (GEE).

In 2007, Jim Gray, a computer scientist at Microsoft until he was lost at sea later that year, was quite prescient when he said: “For data analysis, one possibility is to move the data to you, but the other possibility is to move your query to the data. You can either move your questions or the data. Often it turns out to be more efficient to move the questions than to move the data.” That’s the basic principle behind doing geospatial analytics in the cloud.

In this chapter, you’ll use GEE to perform a variety of tasks associated with geographic properties in spatial environments. We’ll also take a quick look at another tool that integrates with Python: Leafmap. By the end of the chapter, you’ll have enough familiarity with these interfaces to follow along with later chapters and eventually launch your own independent project.

Google Earth Engine Setup

But first, you’ll need to create your work environments. The Jupyter Notebooks for this chapter are available on GitHub. You can open them up and follow along or experiment with the code and explore separately when time permits. The instructions for installing the necessary packages and resources will be covered as well.

The GEE archive contains more than 60 petabytes of satellite imagery and remote sensing and geospatial data—all freely available, preprocessed, and easy to access. Imagine trying to download all that to your laptop! GEE’s algorithms allow the public to create interactive applications or data products in the cloud. You just need to apply for a free Google Earth Engine account (which comes with 250 gigabytes of storage) and authenticate within either the terminal or notebook when you are granted access. Follow these steps:

To authorize access needed by Earth Engine, open the following URL 
in a web browser and follow the instructions:
https://accounts.google.com/o/oauth2/auth?client_id=xxx
The authorization workflow will generate a code, which you should paste 
in the box below
Enter verification code: code will be here

Successfully saved authorization token.

GEE will send you a unique link and verification code. Paste the code into the box and hit Enter.

Using the GEE Console and geemap

The GEE console is a quick resource for locating images and running the code. But Python isn’t GEE’s native language: the GEE code editor is designed for writing and executing scripts in JavaScript. Its Javascript API has a robust IDE, extensive documentation, and interactive visualization functionality, and none of that is natively available for Python. To access the full spectrum of interactivity in a Python environment, you will need to use geemap, a Python package for interacting with GEE created by Dr. Qiusheng Wu.

Fortunately, you can use the extensive GEE catalog to locate and visualize data with a single click, with limited or no JavaScript expertise. You can find your way around the interface and generate maps simply by scrolling through the Scripts tab. Each code script allows you to run JavaScript code and generate maps. But if you’re seeking autonomy to build your own maps and engage interactively, you’ll want to use geemap. The GEE catalog (pictured in Figure 4-1) contains useful information you will need when deciding how to interact with data in geemap.

The GEE console
Figure 4-1. The GEE catalog

Look through the Earth Engine Data Catalog, find a dataset collection, and scroll down the page. At the bottom, you will notice that the JavaScript code is provided. Simply copy and paste it into the console, as shown in Figure 4-2.

Figure 4-2 shows what is generated when you paste the code into the console and select Run from the list of options in the center panel. For example, the data from Figure 4-1 generates USGS Landsat 8 Level 2, Collection 2, Tier 1, identified as ee.ImageCollection("LANDSAT/LC08/C02/T1_L2").

Google Earth Engine IDE
Figure 4-2. Google Earth Engine IDE

Let’s learn how to generate GEE images using Python scripts in a Jupyter Notebook. geemap even has a tool that will convert JavaScript code to Python right in your Jupyter Notebook.

Jupyter Notebook is a separate entity from your Python environments. It was originally named for its ability to to interact with three different coding languages, Julia, Python, and R, but it has expanded well beyond its original capabilities. You have to tell the system which version of Python you want. The kernel is how the Notebook and Python communicate.

Installing geemap will create a console in a Notebook environment similar to what you see in the GEE console but with the Python API instead of JavaScript. Once you set up a Conda environment, you will be able to interact with GEE within a Jupyter Notebook. First, you will need to download the required packages and libraries.

Creating a Conda Environment

Anaconda is a popular platform-agnostic distribution manager for Python and other programming languages that installs and manages Conda packages. You could think of Anaconda as storage for all of your data science tools. Conda manages your packages and tools, allowing you to upload new tools as needed and to customize your work environment.

Conda packages are stored in the Anaconda repository or the cloud, so you don’t need additional tools for installation. Conda allows you to make as many environments as you need with your preferred version of Python. You also have the option of downloading a leaner version of Anaconda called Miniconda, which I prefer, regardless of your operating system. Both are straightforward installations. I recommend the Miniconda installation instructions in this tutorial by Ted Petrou.

Opening the Jupyter Notebook

Jupyter Notebooks are open source, interactive, web-based tools. They run in your browser and don’t require any additional downloads. You can access the Jupyter Notebook for this chapter on GitHub: the filename is 4 Geospatial Analytics in the Cloud. You can find and configure the installed nbextensions in the file menu of your Notebook. These are handy plug-ins that add more functionality to your Jupyter Notebook environment.

Installing geemap and Other Packages

Once you’ve installed your Conda environment, you can open your terminal or command prompt to install geemap. Execute the following code line by line to activate your work environment. Here, I’ve named my geospatial environment gee:

conda create -n gee python=3.9
conda activate gee
conda install geemap -c conda-forge
conda install cartopy -c conda-forge
conda install jupyter_contrib_nbextensions -c conda-forge
jupyter contrib nbextension install --user

Notice that I specified the version of Python to include in the environment. I’ve done this because there are still some dependencies that aren’t ready for the latest version of Python. That is one important reason why environments are useful: you will receive a warning if there are compatibility conflicts, and you can create an environment using the version that will avoid those conflicts. 

This install also includes Cartopy, a Python package for geospatial data processing; jupyter_contrib_nbextensions, a package for expanded functionality; and contrib_nbextensions, which will add styles to the Jupyter configuration.

Now that you’ve installed the packages into your environment, whenever you open a new session, you will only need to run import geemap in a code cell. The environment is now visible when you activate, shown here as (gee):

(gee) MacBook-Pro-8:~ bonnymcclain$ conda list

This environment will contain all of the associated packages as well as their dependencies. You can create different environments (abbreviated as env) that include the dependencies and packages unique to each project.

The conda list command will show you which packages are installed in the active environment. This following is a snippet of what loads for me when I execute the command:

# packages in environment at /Users/bonnymcclain/opt/miniconda3/envs/geo:
#
# Name                         Version                 Build    Channel
aiohttp                        3.7.4          py38h96a0964_0    conda-forge
anyio                          3.1.0          py38h50d1736_0    conda-forge
appnope                        0.1.2          py38h50d1736_1    conda-forge
argon2-cffi                    20.1.0         py38h5406a74_2    conda-forge
async-timeout                  3.0.1                 py_1000    conda-forge
async_generator                1.10                     py_0    conda-forge
attrs                          21.2.0           pyhd8ed1ab_0    conda-forge
backcall                       0.2.0            pyh9f0ad1d_0    conda-forge
backports                      1.0                      py_2    conda-forge
backports.functools_lru_cache  1.6.4            pyhd8ed1ab_0    conda-forge
beautifulsoup4                 4.9.3            pyhb0f4dca_0    conda-forge
bleach                         3.3.0            pyh44b312d_0    conda-forge
bqplot                         0.12.27          pyhd8ed1ab_0    conda-forge
branca                         0.4.2            pyhd8ed1ab_0    conda-forge
brotlipy                       0.7.0       py38h5406a74_1001    conda-forge
bzip2                          1.0.8              h0d85af4_4    conda-forge
c-ares                         1.17.1             h0d85af4_1    conda-forge
ca-certificates                2020.12.5          h033912b_0    conda-forge
cachetools                     4.2.2            pyhd8ed1ab_0    conda-forge
cartopy                        0.19.0.post1   py38h4be4431_0    conda-forge
certifi                        2020.12.5      py38h50d1736_1    conda-forge
cffi                           1.14.5         py38ha97d567_0    conda-forge
chardet                        4.0.0          py38h50d1736_1    conda-forge
click                          8.0.1          py38h50d1736_0    conda-forge
colour                         0.1.5                    py_0    conda-forge
geemap                         0.8.16           pyhd8ed1ab_0    conda-forge
...

This is helpful in case your code throws an error due to a missing dependency. Run conda list; you should see the versions listed as well. Running conda env list will display any environments you already have installed.

I install a kernel (a part of the operating system running in your environment) for each environment that I activate:

conda install ipykernel

Now you can add the kernel to your environment—in this case, <your environment name> is gee:

python -m ipykernel install --user --name myenv --display-name 
"<your environment name>"

Your local computer has to access files. The import statement will add the package as a Python object (that is, a collection of data and methods) into the currently running instance of the program.

Open your Terminal and write jupyter notebook into the console. A Notebook should open in your browser. You will need to import the required libraries into the Notebook. You can see them listed in the code shell. Recall that os allows you to access the operating system where you are running Python, ee is the Earth Engine library, and geemap allows you to interface via Python. You’ll import these libraries using the import function:

import os
import ee
import geemap
#geemap.update_package()

The central component of a computer operating system is the kernel. The kernel is specific to each programming language, and the default kernel depends on what version of Python you are running in your Notebook.

You will need to restart the kernel for the update to take effect. Select Kernel from the menu and scroll to the option to rerun. You are now ready to begin working in the Notebook.

Note the hash symbol (#) in the last line of the previous code block. In Python code, the hash symbol denotes a comment, or a line of the code that won’t run. When you want to run that line of code, delete the hash symbol. To make sure you are using an updated geemap package, uncomment that last line (that is, remove the # in the last row) before running the code. Once you update geemap, you can once again insert the hash, since you won’t need to update the package every time you run the code. You may also add commented text to include any clarifying details. You will see this practice in many of the code blocks in this book.

Exploring the Landsat 9 Image Collection

We have been working with Landsat data, so let’s look at the Landsat 9 data, which was first released in early 2022 and still rolling out as of this writing. To see how much of the dataset is available, run the following code:

collection = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2')
print(collection.size().getInfo())

This outputs: 106919.

The collection includes 106,919 images—and is still increasing!

For comparison, the Landsat/LC08/C02/T1_L2 collection contains 1,351,632 images. By the time this book is published, the number of Landsat 9 images will be vastly larger. You can calculate the median value of all matching bands to reduce the size of the image collection:

median = collection.median()

Working with Spectral Bands

As you learned in Chapter 1, spectral bands are like bins of different types of light. Reflected light is captured as bands of light energy in a range of different wavelengths or colors. Think of the electromagnetic spectrum. Each section of the spectrum is actually a band. The information about bands in this section is intended to highlight where to locate the data to enter into the code to access the correct information. The bands collected by Landsat 8 apply to Landsat 9. You will need this data to apply scaling factors, or comparisons of linear distances that adjust for distortion of areas and angles based on the map projection (also covered in Chapter 1). Remember, the Earth is shaped as an ellipsoid, not a perfect sphere! We derive scaling factors from the Scale and the Offset, as shown in Figure 4-6.

Band characteristics of Landsat 8/9 data
Figure 4-6. Band characteristics of Landsat 8/9 data

The USGS provides guidance on which spectral bands are best for different types of research. You can learn more about the science and explore common Landsat band combinations.

You’ll import ee.ImageCollection into your Jupyter Notebook and add it as a data layer to your map. You’ll then create a composite image from all of the images. This will yield the median value of the spectral bands.

In Python, we define functions by the keyword def. In the following code, the function name is apply_scale_factors, followed by the parameter (image):

def apply_scale_factors(image):
   opticalBands = image.select('SR_B.*').multiply(0.0000275).add(-0.2)
   thermalBands = image.select('ST_B.*').multiply(0.00341802).add(149.0)
   return image.addBands(opticalBands, None, True).addBands(thermalBands, None, 
   True)

The asterisk (*) tells the function that you want to select multiple bands that meet the defined search requirements. Landsat’s sensors are the Operational Land Imager (OLI) and Thermal Infrared Sensor (TIRS). The OLI produces spectral bands 1 through 9, and TIRS consists of two thermal bands: SR_B and ST_B.

The colon (:) signals where the function body begins. Inside the function body, which is indented, the return statement determines the value to be returned. After the function definition is complete, calling the function with an argument returns a value:

dataset = apply_scale_factors(median)

To understand why you would want to pick and choose certain bands, think of them as having a spectral signature. Natural color bands use SR_B4 for red, SR_B3 for green, and SR_B2 for blue. Green indicates healthy vegetation, brown is less healthy, whitish gray typically indicates urban features, and water will appear dark blue or black.

The near-infrared (NIR) composite uses NIR (SR_B5), red (SR_B4), and green (SR_B3). Areas in red have better vegetation health, dark areas are water, and urban areas are white. So include these as your visualization parameters:

vis_natural = {
   'bands': ['SR_B4', 'SR_B3', 'SR_B2'],
   'min': 0.0,
   'max': 0.3,
}

vis_nir = {
   'bands': ['SR_B5', 'SR_B4', 'SR_B3'],
   'min': 0.0,
   'max': 0.3,
}

Now add them as data layers to your map:

Map.addLayer(dataset, vis_natural, 'True color (432)')
Map.addLayer(dataset, vis_nir, 'Color infrared (543)')
Map

In Figure 4-7, I toggled the infrared layer off so you can see the other bands more clearly. There appears to be cloud cover as well. Landsat 9 resamples every 16 days, so it will look different when you view it.

Different band combinations of Landsat 8/9
Figure 4-7. Different band combinations of Landsat 8/9

If you hover your cursor over the toolbar icon, you will see the Layers menu appear. You can change the opacity of any maps and deselect any layers you don’t want to view in the Layers menu. You can also click the gear icon to explore attributes. You can also specify the minimum and maximum values to display. Stretching the data spreads the pixel values, and you can experiment with different values. Your data will show the range of the bands, and you can decide which values you want to display:

vis_params = [
   {'bands': ['SR_B4', 'SR_B3', 'SR_B2'], 'min': 0, 'max': 0.3},
   {'bands': ['SR_B5', 'SR_B4', 'SR_B3'], 'min': 0, 'max': 0.3},
   {'bands': ['SR_B7', 'SR_B6', 'SR_B4'], 'min': 0, 'max': 0.3},
   {'bands': ['SR_B6', 'SR_B5', 'SR_B2'], 'min': 0, 'max': 0.3},
]

To add labels for these layers, create a list of labels:

labels = [
   'Natural Color (4, 3, 2)',
   'Color Infrared (5, 4, 3)',
   'Short-Wave Infrared (7, 6 4)',
   'Agriculture (6, 5, 2)',
]

Then assign a label to each layer:

geemap.linked_maps(
   rows=2,
   cols=2,
   height="400px",
   center=[-3.4653, -62.2159],
   zoom=4,
   ee_objects=[dataset],
   vis_params=vis_params,
   labels=labels,
   label_position="topright",
)

Examining two more parameters in Figure 4-8, you can also see shortwave infrared. Here, darker green indicates dense vegetation, urban areas are shown in blue, healthy vegetation is green, and bare earth is magenta.

Landsat band combinations
Figure 4-8. Landsat band combinations

Let’s apply your introduction to GEE and geemap to begin exploring.

The National Land Cover Database Basemap

The National Land Cover Database (NLCD) tracks land cover in the US. It is freely available in the Earth Engine Data Catalog and is updated every five years. Land cover data includes spatial reference and land surface characteristics, such as tree canopy cover (which we explored in the last chapter), impervious surfaces, and additional patterns of biodiversity and climate changes. Impervious land cover means nonnatural surfaces, such as asphalt, concrete, or other manmade layers, that limit the natural penetration of rainwater into soil. This information can help predict which areas may be more prone to flooding during heavy rains.

In this section, you’ll use NLCD data to perform a Landsat-based examination of the imperviousness data layer (for urban classes) and of decision-tree classification (for the rest). We won’t be doing a full activity here, just a quick orientation, but I encourage you to explore more.

Accessing the Data

Navigate to the Earth Engine Data Catalog and scroll to NLCD_Releases/2019_REL/NLCD or the National Land Cover Database, as shown in Figure 4-9. Earlier we noted that you can simply add this data to the map, but there are a few more options here that I want to show you. Copy the JavaScript code and place it on your clipboard.

The Earth Engine Data Catalog
Figure 4-9. The Earth Engine Data Catalog

The NLCD catalog provides a wealth of information, including date ranges for collection, the data source, an image snippet, a data description, information about the multispectral bands, and image properties.

In geemap, generate a default map of the world:

map = geemap.Map()  
map

Next, select the convert JavaScript icon. The box shown in Figure 4-9 will pop up. Paste the JavaScript code from the catalog into the box. Follow the instructions in the code comments that populate in the pop-up shown in Figure 4-10:

// Import the NLCD collection.
var dataset = ee.ImageCollection('USGS/NLCD_RELEASES/2019_REL/NLCD');

// The collection contains images for multiple years and regions in the USA.
print('Products:', dataset.aggregate_array('system:index'));

// Filter the collection to the 2016 product.
var nlcd2016 = dataset.filter(ee.Filter.eq('system:index', '2016')).first();

// Each product has multiple bands for describing aspects of land cover.
print('Bands:', nlcd2016.bandNames());

// Select the land cover band.
var landcover = nlcd2016.select('landcover');

// Display land cover on the map.
Map.setCenter(-95, 38, 5);
Map.addLayer(landcover, null, 'Landcover');

Once you hit Convert, you will see the code update from JavaScript to Python, as shown in Figure 4-10.

Using geemap to convert a script from JavaScript to Python
Figure 4-10. Using geemap to convert a script from JavaScript to Python

If the code does not update into a new cell in your Jupyter Notebook, you can cut and paste it into a new cell and run the cell. The image will now appear as your map.

Now let’s include the default NLCD legend. Select the landcover layer. To discover which legends are available as defaults, run the builtin_legend function:

legends = geemap.builtin_legends
for legend in legends:
    print(legend)

The NLCD’s legend will be listed as an option. Select it to add it to your map.

Building a Custom Legend

While the NLCD offers a built-in legend option, many datasets do not—and even when they do, these legends don’t always offer exactly what you need. Thus, it’s helpful to be able to create your own map legend. Let’s look at how to do that now.

The classes in a dataset usually correspond to the categories you’d want in a legend. Fortunately, you can convert a class table to a legend.

If your data is from the GEE data catalog, you can find a class table there. Then use the following code (or find this code cell in your Jupyter Notebook) and copy the text from the class table into it:

map = geemap.Map()

legend_dict = {
    '11 Open Water': '466b9f',
    '12 Perennial Ice/Snow': 'd1def8',
    '21 Developed, Open Space': 'dec5c5',
    '22 Developed, Low Intensity': 'd99282',
    '23 Developed, Medium Intensity': 'eb0000',
    '24 Developed High Intensity': 'ab0000',
    '31 Barren Land (Rock/Sand/Clay)': 'b3ac9f',
    '41 Deciduous Forest': '68ab5f',
    '42 Evergreen Forest': '1c5f2c',
    '43 Mixed Forest': 'b5c58f',
    '51 Dwarf Scrub': 'af963c',
    '52 Shrub/Scrub': 'ccb879',
    '71 Grassland/Herbaceous': 'dfdfc2',
    '72 Sedge/Herbaceous': 'd1d182',
    '73 Lichens': 'a3cc51',
    '74 Moss': '82ba9e',
    '81 Pasture/Hay': 'dcd939',
    '82 Cultivated Crops': 'ab6c28',
    '90 Woody Wetlands': 'b8d9eb',
    '95 Emergent Herbaceous Wetlands': '6c9fb8'
}

landcover = ee.Image('USGS/NLCD/NLCD2019').select('landcover')
Map.addLayer(landcover, {}, 'NLCD Land Cover')

Map.add_legend(legend_title="NLCD Land Cover Classification", 
   legend_dict=legend_dict)
Map

You can find more info on building and customizing legends manually in the geemap documentation.

Now you can explore your map and dig deeper into your areas of interest. What questions do you want to ask of this map? Take some time to explore. There are many different ways to customize your maps with a broad selection of tools!

The GEE catalog is extensive. As you explore different databases and datasets using the skills you’ve learned here, you will be able to work with raster and vector data as well as upload your own data sources. A list of handy additional functions in geemap is available on the geemap GitHub page. However, I’d also like to introduce you to an alternative to GEE.

Leafmap: An Alternative to Google Earth Engine

Visualizing geospatial data outside of GEE does not have to be limiting! If you don’t have access to a GEE account or aren’t interested in working with GEE, consider using Leafmap. Leafmap is a Python package that lets you visualize interactive geospatial data in your Jupyter Notebook environment. It is based on the geemap package you have already experienced, but as you will see in this section, Leafmap provides access to geospatial data outside the GEE platform. Its GUI reduces the amount of coding you need to do. It has a variety of open source packages at its core.

Leafmap works with many different plotting backends, including ipyleaflet. (A backend, in this context, is internal code that runs on a server and receives client requests.) Users don’t see backends, but they are always operating nonetheless.

You can access the Jupyter Notebook Leafmap with the GitHub link. Follow the Leafmap documentation for specific installation instructions depending on your version of Python. (If you aren’t sure what version you have, enter python in the terminal, and it will output the number of the version you have installed. This is important to remember in case you run into issues with your installation of packages.)

You can set up a new environment to work with Leafmap. I originally created the Conda environment shown in the following code with Python 3.8, but it is likely to work with later versions. I named this environment geo because it is running in a different version of Python:

conda create -n geo python=3.8
conda activate geo
conda install geopandas
conda install leafmap -c conda-forge
conda install mamba -c conda-forge
mamba install leafmap xarray_leaflet -c conda-forge
conda install jupyter_contrib_nbextensions -c conda-forge
pip install keplergl

As before, to open the Notebook, type jupyter notebook and hit Enter. Now enter the following code into the Notebook to reveal something similar to Figure 4-11:

from ipyleaflet import *
m = Map(center=[48.8566, 2.3522], zoom=10, height=600, widescreen=False,
basemaps=basemaps.Stamen.Terrain)
m
Installing basemaps in Leafmap
Figure 4-11. Installing basemaps in Leafmap

Changing the basemap is as easy as placing your cursor inside the basemap parentheses and selecting Tab on the keyboard. Figure 4-12 shows the options that become available. Esri is the selected basemap here, but you can scroll up and down until you find a suitable one. Be sure to explore. Once you type Esri, options will populate.

Changing basemaps in Leafmap
Figure 4-12. Changing basemaps in Leafmap

Another useful tool is the ability to preset your zoom levels. When you run the cell in your Notebook, you will have the option of sliding between different zoom levels:

m.interact(zoom=(5,10,1))

Figure 4-13 shows the output.

Zoom levels in Leafmap
Figure 4-13. Zoom levels in Leafmap

You can also provide a reference by inserting a minimap into your larger map, as shown in Figure 4-14. To do so, enter the following code:

minimap = Map(
    zoom_control=False, attribution_control=False, 
    zoom=5, center=m.center, basemap=basemaps.Stamen.Terrain
)
minimap.layout.width = '200px'
minimap.layout.height = '200px'
link((minimap, 'center'), (m, 'center'))
minimap_control = WidgetControl(widget=minimap, position='bottomleft')
m.add_control(minimap_control)

The minimap shown in Figure 4-14 will appear, helping users stay oriented in a larger context.

A map within a map: the minimap function in Leafmap
Figure 4-14. A map within a map: the minimap function in Leafmap

Summary

This chapter explored Google Earth Engine and some related tools, libraries, and packages that you can use to answer geospatial questions, and it introduced you to an alternative tool, Leafmap. This chapter and its associated Notebooks will be a handy reference for the projects you’ll do in the next chapter. You have rendered visualizations and created maps on the canvas. Next, you will begin analyzing these relationships and exploring tools to do some advanced analysis of your geospatial data.

Get Python for Geospatial Data Analysis now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.