Published: May 26, 2021
The Global Ecosystem Dynamics Investigation (GEDI) mission aims to characterize ecosystem structure and dynamics to enable radically improved quantification and understanding of the Earth's carbon cycle and biodiversity. The Land Processes Distributed Active Archive Center (LP DAAC) distributes the GEDI Level 1 and Level 2 Version 1 and Version 2 products. The LP DAAC created the GEDI Finder Web Service to allow users to perform spatial queries of GEDI Version 1 L1-L2 full-orbit granules. One of the updates for GEDI Version 2 included additional spatial metadata that allows users to perform spatial queries via a graphical user interface (GUI) using NASA's Earthdata Search or programmatically using NASA's Common Metadata Repository (CMR). Another update is that each GEDI V1 full-orbit granule has been divided into 4 sub-orbit granules in V2.
This tutorial was developed using an example use case for a current GEDI Finder user who has been using the GEDI Finder web service in Python to find intersecting GEDI L2A Version 1 full-orbit granules over the Amazon Rainforest. The user is now looking to use the same workflow to find intersecting GEDI L2A V2 sub-orbit granules.
This tutorial will show how to use Python to perform a spatial query for GEDI V2 data using NASA's CMR, how to reformat the CMR response into a list of links pointing to the intersecting sub-orbit granules on the LP DAAC Data Pool, and how to export the list of links as a text file.
It is recommended to use Conda, an environment manager to set up a compatible Python environment. Download Conda for your OS here: https://www.anaconda.com/download/. Once you have Conda installed, Follow the instructions below to successfully setup a Python environment on Linux, MacOS, or Windows.
This Python Jupyter Notebook tutorial has been tested using Python version 3.8. Conda was used to create the python environment.
conda create -n gedifinder -c conda-forge --yes python=3.8
conda activate gedifinder
jupyter notebook
If you do not have Jupyter Notebook installed, you may need to run:
conda install jupyter notebook
If you prefer to not install Conda, the same setup and dependencies can be achieved by using another package manager such as pip
.
import requests as r
from datetime import datetime
import os
gedi_finder
that takes two user-submitted input values, a product
and a bbox
.bbox
is a string of bounding box coordinate values (decimal degrees) in the following format:Example:
'-73.65,-12.64,-47.81,9.7'
def gedi_finder(product, bbox):
# Define the base CMR granule search url, including LPDAAC provider name and max page size (2000 is the max allowed)
cmr = "https://cmr.earthdata.nasa.gov/search/granules.json?pretty=true&provider=LPDAAC_ECS&page_size=2000&concept_id="
# Set up dictionary where key is GEDI shortname + version
concept_ids = {'GEDI01_B.002': 'C1908344278-LPDAAC_ECS',
'GEDI02_A.002': 'C1908348134-LPDAAC_ECS',
'GEDI02_B.002': 'C1908350066-LPDAAC_ECS'}
# CMR uses pagination for queries with more features returned than the page size
page = 1
bbox = bbox.replace(' ', '') # remove any white spaces
try:
# Send GET request to CMR granule search endpoint w/ product concept ID, bbox & page number, format return as json
cmr_response = r.get(f"{cmr}{concept_ids[product]}&bounding_box={bbox}&pageNum={page}").json()['feed']['entry']
# If 2000 features are returned, move to the next page and submit another request, and append to the response
while len(cmr_response) % 2000 == 0:
page += 1
cmr_response += r.get(f"{cmr}{concept_ids[product]}&bounding_box={bbox}&pageNum={page}").json()['feed']['entry']
# CMR returns more info than just the Data Pool links, below use list comprehension to return a list of DP links
return [c['links'][0]['href'] for c in cmr_response]
except:
# If the request did not complete successfully, print out the response from CMR
print(r.get(f"{cmr}{concept_ids[product]}&bounding_box={bbox.replace(' ', '')}&pageNum={page}").json())
gedi_finder
function to variables.# User-provided inputs (UPDATE FOR YOUR DESIRED PRODUCT AND BOUNDING BOX REGION OF INTEREST)
product = 'GEDI02_B.002' # Options include 'GEDI01_B.002', 'GEDI02_A.002', 'GEDI02_B.002'
bbox = '-73.65,-12.64,-47.81,9.7' # bounding box coordinates in LL Longitude, LL Latitude, UR Longitude, UR Latitude format
GEDI02_B.002
product for a bounding box covering the Amazon Rainforest.gedi_finder
function for the desired product and bounding box region of interest defined above, and set the output to a variable.granules = gedi_finder(product, bbox)
print(f"{len(granules)} {product} Version 2 granules found.")
938 GEDI02_B.002 Version 2 granules found.
granules
list of Data Pool links for intersecting GEDI V2 granules and export as a text file. The text file will be written to your current working directory, and will be named based on the date and time that the file was created.# Set up output text file name using the current datetime
outName = f"{product.replace('.', '_')}_GranuleList_{datetime.now().strftime('%Y%m%d%H%M%S')}.txt"
# Open file and write each granule link on a new line
with open(outName, "w") as gf:
for g in granules:
gf.write(f"{g}\n")
print(f"File containing links to intersecting {product} Version 2 data has been saved to:\n {os.getcwd()}\{outName}")
File containing links to intersecting GEDI02_B.002 Version 2 data has been saved to:
D:\GEDI_Finder\GEDI_Finder_Results_20210507074324.txt
Explains how to perform spatial querying and subsetting of GEDI V2 data directly in NASA's Earthdata Search Client
Allows you to subset GEDI V2 data by band/layer and region of interest
Includes a series of tutorials that demonstrate how to start working with GEDI V2 data in Python.