Difference between revisions of "Google Earth Engine to look for and download imagery"

From CUOSGwiki
Jump to navigationJump to search
(Added in a "point of interest" in an attempt to debug scripting error)
(removing the point of interest, that wasn't the bug, was just missing some parentheses. Add print statements and explain)
Line 38: Line 38:
   
 
This seems like a good time to save our work so far. Click on the save button at the top of your script window. When it is saved, the save button should become greyed out.
 
This seems like a good time to save our work so far. Click on the save button at the top of your script window. When it is saved, the save button should become greyed out.
 
In addition to the AREA of interest, we're going to define one point within that area, to facilitate very simple searches of the GEE data archives. Click on the "Geometry imports" rectangle near the top left of your map, then click on "+ new layer" to create a new layer with the default name "geometry" underneath your AOI. Rename the layer to "POI", just as you did with the AOI layer, above, but this time leave the "Import as" entry set to Geometry. In the toolbar, choose button that looks like push-pin in the tool bar (it's the "Add a marker" tool), then "drop a pin" (click with your mouse) anywhere within your AOI polygon on the map.
 
   
 
Click into line 1 in your script window and type or paste the following text
 
Click into line 1 in your script window and type or paste the following text
Line 45: Line 43:
 
var landsat_8_collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
 
var landsat_8_collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
 
.filterDate('2017-01-01', '2023-12-31')
 
.filterDate('2017-01-01', '2023-12-31')
.filterBounds(POI);
+
.filterBounds(AOI);
  +
   
 
That's actually one declaration of a variable, split across a few lines for legibility. The first line shows that we are declaring a variable called landsat_8_collection, and the ee.ImageCollection function tells the system we want to access the USGS collection of Landsat 8, Tier 1 (first level of USGS screening), Level 2 (atmospherically corrected surface reflectance data) images ([https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC08_C02_T1_L2 see this link for more details]). But then in the next two lines, the leading "." means that we are applying further processing to the preceding line(s); I have specified 2 filters for searching the data collection by adding a time window (the .filterDate line) of 1 Jan 2017 to 31 Dec 2023, and then in the next line asking only to include images that intersect our area of interest polygon.
 
That's actually one declaration of a variable, split across a few lines for legibility. The first line shows that we are declaring a variable called landsat_8_collection, and the ee.ImageCollection function tells the system we want to access the USGS collection of Landsat 8, Tier 1 (first level of USGS screening), Level 2 (atmospherically corrected surface reflectance data) images ([https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC08_C02_T1_L2 see this link for more details]). But then in the next two lines, the leading "." means that we are applying further processing to the preceding line(s); I have specified 2 filters for searching the data collection by adding a time window (the .filterDate line) of 1 Jan 2017 to 31 Dec 2023, and then in the next line asking only to include images that intersect our area of interest polygon.
 
   
 
Next we'll go from the preceding collection of images to picking out a single image. There are many ways one might want to do this, depending on the desired purpose for the image; we could explore the collection interactively, or choose specific timing... but for simplicity in a demonstration, I'll ask the system to search through all the images and look at the metadata about cloud cover, sorting the collection in order of that data, and selecting the first image in the list (the one with the least cloud cover. Paste the following code at the end of your existing script:
 
Next we'll go from the preceding collection of images to picking out a single image. There are many ways one might want to do this, depending on the desired purpose for the image; we could explore the collection interactively, or choose specific timing... but for simplicity in a demonstration, I'll ask the system to search through all the images and look at the metadata about cloud cover, sorting the collection in order of that data, and selecting the first image in the list (the one with the least cloud cover. Paste the following code at the end of your existing script:
   
  +
print(landsat_8_collection);
 
var landsat_8_chooseBest = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
 
var landsat_8_chooseBest = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
 
.filterDate('2017-01-01', '2023-12-31')
 
.filterDate('2017-01-01', '2023-12-31')
.filterBounds(myQueryPoint)
+
.filterBounds(AOI)
 
.sort('CLOUD_COVER')
 
.sort('CLOUD_COVER')
 
.first();
 
.first();
 
print(landsat_8_chooseBest);
 
print(landsat_8_chooseBest);
  +
  +
Save your script again, then press the Run button to the right of Save. Output should appear in the Console area at the top right of the interface. Let's go over what each of the lines of code above accomplished, and how it relates to what appears in the console.
  +
  +
The first lines, declaring the variable identifying our initial collection of images, produces no output - it just runs in the background, defining the requested subset of images. Adding the print statement causes information ABOUT that object to show up in the console. In the console window, click on the little triangle icon that is immediately to the left of "ImageCollection", and it should expand into a hierarchy of information about the collection. Explore that, and you should be able to find out how images were found (in my area, there were 428 images), and even go right down into information about each band of each image.
  +
  +
Next, we defined a new variable landsat_8_chooseBest, and again called on ee.ImageCollection, but this time we did the sorting based on cloud cover, and then called on print() to give us metadata in the Console window about the image that was selected. Click on the triangle to confirm there is now metadata about only one image showing up.
  +
  +
[[File:Screenshot2024-03-14_135019.png|618px|thumb|none|Console output about the best ranked image by cloud cover]]

Revision as of 13:52, 14 March 2024

Google Earth Engine (GEE) is a web/cloud-based service that brings together many open spatial data sets including imagery and other spatial data, plus analytical tools and processing capabilities that allow users to work with spatial data at very high spatial extents. Google provides free access to this service for research and educational purposes, and also provides fee-based access to commercial users. Because it brings together so many open geospatial datasets in one location, many users primarily access the service for that reason alone. This tutorial aims to demonstrate how this could be done, with one specific example, but the approach could be easily generalized. Future edits to the tutorial could expand to show other datasets and/or pre-processing steps prior to the download. There are two APIs for accessing the service; the original, used by this tutorial, employs Javascript, but there is also a Python-based alternative.

Prerequisites

You will require a Google account that you can log in to. If you have one that has a higher storage limit, you may want to choose that one, because we will use Google Drive to get access to the images that we want to download.

You also need to go through a one-time signup process for the GEE service. Use this link to sign up for the GEE service. If you are using / have previously used any Google logins in your browser, it should detect that, and if you have used more than one Google account it should prompt you which one to sign up with.

At the end of this tutorial, we will use local software to take a look at a local copy of the image we extracted. You can use any program that is capable of reading a GeoTIFF image. QGIS is one free open source option, and will be used in the example below.

Logging in to the Code Editor and creating a new script

If you are not already there through the signup process, or whenever you want to return to your account, you can to the code editor here.

You should end up with a browser window looking something like this:

Code Editor Screenshot

The area at top left opens by default to a tab called "scripts" which contains an initially empty "sandbox" where you can create your own scripts, and if you scroll down, perhaps the most interesting sections you'll see are the "examples" and "demos" sections. You can explore there on your own. We're going to start by creating a new script in your sandbox. Click on the red "New" button at the top of Scripts tab, choose the File option, and then input an appropriate name for your script (I'll use "findGetImage"). Click on the resulting entry in your sandbox, and you should see your script name appear at the top left of the code writing window immediately to the right of the script list.

Choose and digitize an area of interest (AOI)

The bottom half of the code editor is used for navigating and manipulating maps. If you have never used the interface before, it is likely showing you a map showing most of the continental United States. The controls should be familiar if you have ever used Google Maps or similar software. Use the mouse/trackpad to pan to the area of the globe you are interested in, and then the + and - icons near the top left of the map to zoom to an appropriate spatial extent. In the example below, I have zoomed into an area surrounding our campus - Carleton University, in Ottawa, Ontario, Canada.

Now we're going to draw a rectangle to define our area of interest, so that in a future step we can clip our selected imagery data to this selected subset. Click on "Draw a rectangle" button on the tool bar (circled in red in the screenshot below).

Zoomed Map Screenshot

After you click on the tool to draw a rectangle, graphics similar to the following should show up on the screen to the right of that tool bar:

Toolbar closeup

Move the mouse pointer over to where it says "geometry" and click on the gear icon. In the resulting pop-up, change the name from "geometry" to "AOI", and in the drop-down menu below that, choose "FeatureCollection", as illustrated below:

Change the name to AOI and make it a FeatureCollection

Note that you now have a "var" (variable) called AOI showing up as an Import at the top of your script window (centre top of the interface). In the GEE Javascript environment, all the spatial layers you will access will be declared and accessed using a variable. In this case it has been declared as a FeatureCollection, but so far it's a collection of 0 items. Let's fix that, by digitizing a rectangle to use as the area of interest, by clicking your mouse button at one corner of the desired area on the map, dragging down to the opposite corner and releasing the button (i.e. using your mouse to draw a rectangle). When you finish, the rectangle should remain on the screen, and there should be 1 element showing up as belonging to the AOI feature class in the script window.

This seems like a good time to save our work so far. Click on the save button at the top of your script window. When it is saved, the save button should become greyed out.

Click into line 1 in your script window and type or paste the following text

// access the Landsat 8 image collection
var landsat_8_collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
 .filterDate('2017-01-01', '2023-12-31')
 .filterBounds(AOI);

That's actually one declaration of a variable, split across a few lines for legibility. The first line shows that we are declaring a variable called landsat_8_collection, and the ee.ImageCollection function tells the system we want to access the USGS collection of Landsat 8, Tier 1 (first level of USGS screening), Level 2 (atmospherically corrected surface reflectance data) images (see this link for more details). But then in the next two lines, the leading "." means that we are applying further processing to the preceding line(s); I have specified 2 filters for searching the data collection by adding a time window (the .filterDate line) of 1 Jan 2017 to 31 Dec 2023, and then in the next line asking only to include images that intersect our area of interest polygon.

Next we'll go from the preceding collection of images to picking out a single image. There are many ways one might want to do this, depending on the desired purpose for the image; we could explore the collection interactively, or choose specific timing... but for simplicity in a demonstration, I'll ask the system to search through all the images and look at the metadata about cloud cover, sorting the collection in order of that data, and selecting the first image in the list (the one with the least cloud cover. Paste the following code at the end of your existing script:

print(landsat_8_collection);
var landsat_8_chooseBest = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
 .filterDate('2017-01-01', '2023-12-31')
 .filterBounds(AOI)
 .sort('CLOUD_COVER')
 .first();
print(landsat_8_chooseBest);

Save your script again, then press the Run button to the right of Save. Output should appear in the Console area at the top right of the interface. Let's go over what each of the lines of code above accomplished, and how it relates to what appears in the console.

The first lines, declaring the variable identifying our initial collection of images, produces no output - it just runs in the background, defining the requested subset of images. Adding the print statement causes information ABOUT that object to show up in the console. In the console window, click on the little triangle icon that is immediately to the left of "ImageCollection", and it should expand into a hierarchy of information about the collection. Explore that, and you should be able to find out how images were found (in my area, there were 428 images), and even go right down into information about each band of each image.

Next, we defined a new variable landsat_8_chooseBest, and again called on ee.ImageCollection, but this time we did the sorting based on cloud cover, and then called on print() to give us metadata in the Console window about the image that was selected. Click on the triangle to confirm there is now metadata about only one image showing up.

Console output about the best ranked image by cloud cover