Introduction to the GEDI02_B Product¶
Source: https://lpdaac.usgs.gov/products/gedi02_bv002/
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 GEDI instrument produces high resolution laser ranging observations of the 3-dimensional structure of the Earth. GEDI is attached to the International Space Station (ISS) and collects data globally between 51.6° N and 51.6° S latitudes at the highest resolution and densest sampling of any light detection and ranging (lidar) instrument in orbit to date. Each GEDI Version 2 granule encompasses one-fourth of an ISS orbit and includes georeferenced metadata to allow for spatial querying and subsetting.
The purpose of the GEDI Level 2B Canopy Cover and Vertical Profile Metrics product (GEDI02_B) is to extract biophysical metrics from each GEDI waveform. These metrics are based on the directional gap probability profile derived from the L1B waveform. Metrics provided include canopy cover, Plant Area Index (PAI), Plant Area Volume Density (PAVD), and Foliage Height Diversity (FHD). The GEDI02_B product is provided in HDF5 format and has a spatial resolution (average footprint) of 25 meters.
The GEDI02_B data product contains 96 layers for each of the eight-beam ground transects (or laser footprints located on the land surface). Datasets provided include precise latitude, longitude, elevation, height, canopy cover, and vertical profile metrics. Additional information for the layers can be found in the GEDI Level 2B Data Dictionary.
Opening GEDI02_B files and exploring its datasets¶
This tutorial opens and exampines a GEDI02_B file and demonstrates how to plot a subset of points in order to understand the spatial extent of that file.
- Author: Aimee Barciauskas
- Date: December 16, 2022
Resources used: * Getting Started with GEDI L2B Version 2 Data in Python (LPDAAC Tutorial)
[1]:
import boto3
import folium
import h5py
from os.path import exists
from pystac_client import Client
import pandas as pd
[2]:
# STAC API root URL
URL = 'https://stac.maap-project.org/'
client = Client.open(URL)
[3]:
collection = 'GEDI02_B'
search = client.search(
max_items = 1,
collections = collection,
)
[4]:
item = search.get_all_items()[0]
item
[4]:
Item: GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002
ID: GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002 |
Bounding Box: [-0.7023033, 71.1578654, 37.1478474, 104.9249153] |
Datetime: 2021-10-26 19:55:57+00:00 |
links: [{'rel': 'http://esipfed.org/ns/fedsearch/1.1/s3#', 'href': 's3://nasa-maap-data-store/file-staging/nasa-map/GEDI02_B___002/2021.10.26/GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002.h5', 'title': 'File to download', 'hreflang': 'en-US'}, {'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#', 'href': 'https://doi.org/10.5067/GEDI/GEDI02_B.002', 'hreflang': 'en-US', 'inherited': True}, {'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#', 'href': 'https://gedi.umd.edu/', 'hreflang': 'en-US', 'inherited': True}, {'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#', 'href': 'https://lpdaac.usgs.gov/products/gedi02_bv002/', 'hreflang': 'en-US', 'inherited': True}, {'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#', 'href': 'https://lpdaac.usgs.gov/documents/587/gedi_l2b_dictionary_P001_v1.html', 'hreflang': 'en-US', 'inherited': True}, {'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#', 'href': 'https://doi.org/10.5067/DOC/GEDI/GEDI_WF_ATBD.001', 'hreflang': 'en-US', 'inherited': True}, {'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#', 'href': 'https://doi.org/10.5067/DOC/GEDI/GEDI_FCCVPM_ATBD.001', 'hreflang': 'en-US', 'inherited': True}] |
title: SC:GEDI02_B.002:2535637762 |
updated: 2022-02-14T11:13:01.779000+00:00 |
datetime: 2021-10-26T19:55:57+00:00 |
polygons: [['-0.7023033 71.2182943 2.354886 73.3721461 5.40602 75.5359782 8.4470647 77.7245161 11.4737576 79.9520441 14.4776101 82.2328768 17.4528475 84.581811 20.3945452 87.0176579 23.2899312 89.5553904 26.1292472 92.2127668 28.9138899 95.0177972 31.6211459 97.9863264 34.2652642 101.1094587 36.7887039 104.4702505 37.1141145 104.9249153 37.1478474 104.8876228 36.8247731 104.4258301 34.3371102 101.0515014 31.6917218 97.9279295 28.9833121 94.9587677 26.1974318 92.1526624 23.3538027 89.4933633 20.4574165 86.9556826 17.5171465 84.520988 14.5410078 82.1720356 11.5365979 79.8912794 8.5102429 77.6641317 5.4733141 75.4779216 2.4164934 73.3113904 -0.6396876 71.1578654 -0.7023033 71.2182943']] |
time_end: 2021-10-26T21:28:52.000Z |
concept_id: G1201969737-NASA_MAAP |
dataset_id: GEDI L2B Canopy Cover and Vertical Profile Metrics Data Global Footprint Level V002 |
time_start: 2021-10-26T19:55:57.000Z |
browse_flag: False |
data_center: NASA_MAAP |
granule_size: 246.895 |
day_night_flag: UNSPECIFIED |
original_format: ECHO10 |
coordinate_system: GEODETIC |
online_access_flag: False |
producer_granule_id: GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002.h5 |
collection_concept_id: C1201460047-NASA_MAAP |
stac_extensions: [] |
Assets
Asset: None
href: s3://nasa-maap-data-store/file-staging/nasa-map/GEDI02_B___002/2021.10.26/GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002.h5 |
Media type: application/x-hdf5 |
Roles: ['data'] |
Owner: |
Asset: None
href: https://doi.org/10.5067/GEDI/GEDI02_B.002 |
Roles: ['metadata'] |
Owner: |
Asset: None
href: https://lpdaac.usgs.gov/documents/587/gedi_l2b_dictionary_P001_v1.html |
Roles: ['documentation'] |
Owner: |
Links
Link:
Rel: collection |
Target: https://stac.maap-project.org/collections/GEDI02_B |
Media Type: application/json |
Link:
Rel: parent |
Target: https://stac.maap-project.org/collections/GEDI02_B |
Media Type: application/json |
Link:
maap-stac
Rel: root |
Target: |
Media Type: application/json |
Link:
Rel: self |
Target: https://stac.maap-project.org/collections/GEDI02_B/items/GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002 |
Media Type: application/geo+json |
Access and open the GEDI02_B HDF5 file¶
Below, we break down the S3 URL into its bucket and key components to support downloading the file with S3. Note, this will only work on platforms configured with access to the GEDI directory of the NASA MAAP Data Store (s3://nasa-maap-data-store/GEDI*
). Further, it is strongly preferred that any transfer of data is done on AWS services in AWS region us-west-2 in order for data transfer costs to be minimized.
[5]:
href = item.assets['data'].href
path_parts = href.split('/')
bucket = path_parts[2]
key = href.split(bucket)[1][1:]
filename = path_parts[-1]
bucket, key, filename
[5]:
('nasa-maap-data-store',
'file-staging/nasa-map/GEDI02_B___002/2021.10.26/GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002.h5',
'GEDI02_B_2021299195557_O16268_02_T06679_02_003_01_V002.h5')
[14]:
# don't want to run this more than once!
s3 = boto3.client('s3')
if exists(filename):
print("file already downloaded")
else:
s3.download_file(bucket, key, filename)
print("finished downloading")
file already downloaded
[15]:
gediL2B = h5py.File(filename, 'r')
[16]:
beamNames = [g for g in gediL2B.keys() if g.startswith('BEAM')]
beamNames
[16]:
['BEAM0000',
'BEAM0001',
'BEAM0010',
'BEAM0011',
'BEAM0101',
'BEAM0110',
'BEAM1000',
'BEAM1011']
List all the science data sets¶
to understand what type of data is stored in this dataset better.
[ ]:
beam = beamNames[0]
gediL2B_objs = []
gediL2B.visit(gediL2B_objs.append) # Retrieve list of datasets
gediSDS = [o for o in gediL2B_objs if isinstance(gediL2B[o], h5py.Dataset)] # Search for relevant SDS inside data file
[i for i in gediSDS if beam in i][0:20]
Plot a subset of the points¶
First, we create a subset of points to facilitate plotting.
[19]:
lonSample, latSample, shotSample, qualitySample, beamSample = [], [], [], [], [] # Set up lists to store data
# Open the SDS
lats = gediL2B[f'{beamNames[0]}/geolocation/lat_lowestmode'][()]
lons = gediL2B[f'{beamNames[0]}/geolocation/lon_lowestmode'][()]
shots = gediL2B[f'{beamNames[0]}/geolocation/shot_number'][()]
quality = gediL2B[f'{beamNames[0]}/l2b_quality_flag'][()]
# Take every 1000th shot and append to list
for i in range(len(shots)):
if i % 1000 == 0:
shotSample.append(str(shots[i]))
lonSample.append(lons[i])
latSample.append(lats[i])
qualitySample.append(quality[i])
beamSample.append(beamNames[0])
# Write all of the sample shots to a dataframe
latslons = pd.DataFrame({'Beam': beamSample, 'Shot Number': shotSample, 'Longitude': lonSample, 'Latitude': latSample,
'Quality Flag': qualitySample})
latslons
[19]:
Beam | Shot Number | Longitude | Latitude | Quality Flag | |
---|---|---|---|---|---|
0 | BEAM0000 | 162680000200086772 | 71.176248 | -0.652634 | 0 |
1 | BEAM0000 | 162680000200087772 | 71.475272 | -0.228396 | 0 |
2 | BEAM0000 | 162680000200088772 | 71.772920 | 0.194259 | 0 |
3 | BEAM0000 | 162680000200089772 | 72.070465 | 0.616924 | 0 |
4 | BEAM0000 | 162680000200090772 | 72.369240 | 1.040828 | 0 |
... | ... | ... | ... | ... | ... |
89 | BEAM0000 | 162680000200175772 | 102.130037 | 35.159365 | 0 |
90 | BEAM0000 | 162680000200176772 | 102.593719 | 35.509484 | 0 |
91 | BEAM0000 | 162680000200177772 | 103.061891 | 35.857398 | 0 |
92 | BEAM0000 | 162680000200178772 | 103.522337 | 36.194505 | 0 |
93 | BEAM0000 | 162680000200179772 | 103.755363 | 36.363258 | 0 |
94 rows × 5 columns
[22]:
map = folium.Map(
location=[
latslons.Latitude.mean(),
latslons.Longitude.mean()
], zoom_start=3, control_scale=True
)
for index, location_info in latslons.iterrows():
folium.Circle(
[location_info["Latitude"], location_info["Longitude"]],
popup=f"Shot Number: {location_info['Shot Number']}"
).add_to(map)
map
[22]: