import os
import h5py
import pandas
import geopandas
from shapely.geometry import Point
import geoviews
from geoviews import opts, tile_sources as gvts
import shapely
import earthaccess
import warnings
from datetime import datetime
from shapely.errors import ShapelyDeprecationWarning
'bokeh','matplotlib')
geoviews.extension("ignore", category=ShapelyDeprecationWarning) warnings.filterwarnings(
How to work with GEDI Level 2B V002 Data
This tutorial was developed as a walkthrough at the SPACE AND SUSTAINABILITY
,first international colloquiqm, on Nov 16, 2023 in Guadalajara, Jal., Mexico.
This tutorial will show how to use Python to open GEDI L2B Version 2 files, subset layer and to a region of interest, filter by quality, and visualize GEDI Elevation, Canopy Elevation, Plant Area Index,and Canopy Height.
A small area of Reserva de la Biósfera de Calakmul
National Forest is used as the ROI for this tutorial.
Note: Follow the steps provided in setup instructions to create a local Python environment to execute this notebook.
1. Set Up the Working Environment
Import the required packages and set the input/working directory to run this Jupyter Notebook locally.
= os.getcwd() # Set input directory to the current working directory
inDir # os.chdir(inDir)
= inDir.rsplit('2023-ssc')[0] + 'shared/2023SSC/'
data_dir data_dir
'/home/jovyan/shared/2023SSC/'
2. Authentication and Search for GEDI Data
Login to your NASA Earthdata account and create a .netrc file using the login function from the earthaccess library. If you do not have an Earthdata Account, you can create one here.
# authenticate
earthaccess.login()
EARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive)
You're now authenticated with NASA Earthdata Login
Using token with expiration date: 12/24/2023
Using .netrc file for EDL
<earthaccess.auth.Auth at 0x7fe0af014160>
Below, earthaccess
library is used to find GEDI L2B V2 Granules for an area of interest and a temporal range. The .h5 file will be downloaded to the data
folder. You will need to download the files in order to execute this tutorial.
# Define query parameters
= ["C1908350066-LPDAAC_ECS"]
conceptID = (-91.5,18,-89,19) # Lower lon, lower lat, upper lon, upper lat
bbx = ('2022-06-01', '2022-06-30') #'2022-04-01', '2022-08-30'
tempRange # search
= earthaccess.search_data(
results # short_name = 'GEDI02_B'
= conceptID,
concept_id = bbx,
bounding_box =tempRange,
temporal=500
count )
Granules found: 5
Next, download the granules.
Note: Considering the time limitations in this workshop, the download section will be skipped. The downloaded granules are stored in shared
folder and they are accessible to execute this notebook.
# # download
# downloaded_files = earthaccess.download(
# results,
# local_path= f'{data_dir}/data', # Update the directory only to avoid overwritting by attendees
# )
Next, retrieve the granule downloaded.
= [g for g in os.listdir(data_dir) if g.startswith('GEDI02_B') and g.endswith('.h5')] # List all GEDI L2B .h5 files in inDir
gediFiles gediFiles
['GEDI02_B_2022155015315_O19683_03_T05652_02_003_01_V002.h5',
'GEDI02_B_2022159001702_O19744_03_T08957_02_003_01_V002.h5',
'GEDI02_B_2022158145957_O19738_02_T03565_02_003_01_V002.h5',
'GEDI02_B_2022154163608_O19677_02_T01836_02_003_01_V002.h5',
'GEDI02_B_2022162224038_O19805_03_T06723_02_003_02_V002.h5']
The standard format for GEDI Version 2 filenames is as follows:
GEDI02_B: Product Short Name
2022120091720: Julian Date and Time of Acquisition (YYYYDDDHHMMSS)
O19145: Orbit Number
02: Sub-Orbit Granule Number (1-4)
T09106: Track Number (Reference Ground Track)
02: Positioning and Pointing Determination System (PPDS) type (00 is predict, 01 rapid, 02 and higher is final)
003: PGE Version Number
01: Granule Production Version
V002: Product Version
2. Open a GEDI HDF5 File and Read File Metadata
3. Read SDS Metadata and Subset by Beam
The GEDI instrument consists of 3 lasers producing a total of 8 beam ground transects. The eight remaining groups contain data for each of the eight GEDI beam transects. For additional information, be sure to check out: https://gedi.umd.edu/instrument/specifications/.
One useful piece of metadata to retrieve from each beam transect is whether it is a full power beam or a coverage beam. GEDI coverage beams will not penetrate dense forest. The GEDI coverage beams were only designed to penetrate canopies of up to 95% canopy cover under “average” conditions, so users should use GEDI Full power beams in the case of dense forest.
for beam in list(L2B.keys()):
if beam == 'METADATA':
continue
else:
print(beam, 'is:', L2B[beam].attrs['description'])
BEAM0000 is: Coverage beam
BEAM0001 is: Coverage beam
BEAM0010 is: Coverage beam
BEAM0011 is: Coverage beam
BEAM0101 is: Full power beam
BEAM0110 is: Full power beam
BEAM1000 is: Full power beam
BEAM1011 is: Full power beam
Identify all the datasets in the GEDI HDF5 file below.
# list(L2B['BEAM1011'].keys())
= []
L2B_objs # Retrieve list of datasets
L2B.visit(L2B_objs.append) = [o for o in L2B_objs if isinstance(L2B[o], h5py.Dataset)] # Search for relevant SDS inside data file
SDS len(SDS)
1576
Print the datasets available in this L2B granule and print the description for desired datasets.
30] SDS[:
['BEAM0000/algorithmrun_flag',
'BEAM0000/ancillary/dz',
'BEAM0000/ancillary/l2a_alg_count',
'BEAM0000/ancillary/maxheight_cuttoff',
'BEAM0000/ancillary/rg_eg_constraint_center_buffer',
'BEAM0000/ancillary/rg_eg_mpfit_max_func_evals',
'BEAM0000/ancillary/rg_eg_mpfit_maxiters',
'BEAM0000/ancillary/rg_eg_mpfit_tolerance',
'BEAM0000/ancillary/signal_search_buff',
'BEAM0000/ancillary/tx_noise_stddev_multiplier',
'BEAM0000/beam',
'BEAM0000/channel',
'BEAM0000/cover',
'BEAM0000/cover_z',
'BEAM0000/fhd_normal',
'BEAM0000/geolocation/degrade_flag',
'BEAM0000/geolocation/delta_time',
'BEAM0000/geolocation/digital_elevation_model',
'BEAM0000/geolocation/elev_highestreturn',
'BEAM0000/geolocation/elev_lowestmode',
'BEAM0000/geolocation/elevation_bin0',
'BEAM0000/geolocation/elevation_bin0_error',
'BEAM0000/geolocation/elevation_lastbin',
'BEAM0000/geolocation/elevation_lastbin_error',
'BEAM0000/geolocation/height_bin0',
'BEAM0000/geolocation/height_lastbin',
'BEAM0000/geolocation/lat_highestreturn',
'BEAM0000/geolocation/lat_lowestmode',
'BEAM0000/geolocation/latitude_bin0',
'BEAM0000/geolocation/latitude_bin0_error']
print('rh100: ', L2B['BEAM0101/rh100'].attrs['description'])
print('Quality Flag: ', L2B['BEAM0101/l2b_quality_flag'].attrs['description'])
rh100: Height above ground of the received waveform signal start (rh[101] from L2A)
Quality Flag: Flag simpilfying selection of most useful data for Level 2B
View the GEDI L2B Dictionary for more details.
4. Subset by Layer and Filter by Quality
below are the list of datasets will be read and then used to generate a pandas
dataframe.
Label | Description | Units |
---|---|---|
lat_lowestmode | Latitude of center of lowest mode | degree |
lon_lowestmode | Longitude of center of lowest mode | degree |
elev_lowestmode | elevation of center of lowest mode relative to reference ellipsoid | m |
elev_highestreturn | elevation of highest detected return relative to reference ellipsoid | m |
shot_number | Unique shot ID | counter |
l2b_quality_flag | Flag simpilfying selection of most useful data for Level 2B** | - |
degrade_flag | Non-zero values indicate the shot occured during a degraded period. A non-zero tens digit indicates degraded attitude, a non-zero ones digit indicates a degraded trajectory. 3X=ADF CHU solution unavailable (ST-2); 4X=Platform attitude; 5X=Poor solution (filter covariance large); 6X=Data outage (platform attitude gap also); 7X=ST 1+2 unavailable (similar boresight FOV); 8X=ST 1+2+3 unavailable; 9X=ST 1+2+3 and ISS unavailable; X1=Maneuver; X2=GPS data gap; X3=ST blinding; X4=Other; X5=GPS receiver clock drift; X6=X5+X1; X7=X5+X2; X8=X5+X3; X9=X5+X4 | - |
pai | Total plant area index | m2/m2 |
rh100 | Height above ground of the received waveform signal start (rh[101] from L2A) | cm |
** quality_flag is a summation of several individual quality assessment parameters and other flags and is intended to provide general guidance only. A quality_flag value of 1 indicates the cover and vertical profile metrics represent the land surface and meet criteria based on waveform shot energy, sensitivity, amplitude, and real-time surface tracking quality, and the quality of extended Gaussian fitting to the lowest mode.
= ['Beam', 'Shot Number', 'Longitude', 'Latitude', 'Quality Flag', 'Canopy Elevation (m)',
columns'Elevation (m)', 'Plant Area Index', 'Canopy Height/rh100 (cm)', 'Degrade Flag']
= pandas.DataFrame(columns=columns)
latslons_f1
= ['BEAM0000', 'BEAM0001', 'BEAM0010', 'BEAM0011', 'BEAM0101', 'BEAM0110', 'BEAM1000', 'BEAM1011' ]
beamNames for beamname in beamNames:
# Open the SDS
= L2B[f'{beamname}/geolocation/lat_lowestmode'][()]
lats = L2B[f'{beamname}/geolocation/lon_lowestmode'][()]
lons = L2B[f'{beamname}/geolocation/elev_lowestmode'][()]
elevs = L2B[f'{beamname}/geolocation/shot_number'][()].astype(str)
shots = L2B[f'{beamname}/l2b_quality_flag'][()]
quality = L2B[f'{beamname}/pai'][()]
pai = L2B[f'{beamname}/rh100'][()]
rh100 = L2B[f'{beamname}/geolocation/degrade_flag'][()]
degrade_flag = L2B[f'{beamname}/geolocation/elev_highestreturn'][()]
canopy
= pandas.DataFrame({'Beam':beamname, 'Shot Number':shots, 'Longitude':lons, 'Latitude':lats, 'Quality Flag':quality,
latslons 'Canopy Elevation (m)':canopy, 'Elevation (m)':elevs, 'Plant Area Index':pai,
'Canopy Height/rh100 (cm)':rh100, 'Degrade Flag':degrade_flag})
= pandas.concat([latslons_f1, latslons],join="inner")
latslons_f1
latslons_f1
Beam | Shot Number | Longitude | Latitude | Quality Flag | Canopy Elevation (m) | Elevation (m) | Plant Area Index | Canopy Height/rh100 (cm) | Degrade Flag | |
---|---|---|---|---|---|---|---|---|---|---|
0 | BEAM0000 | 196830000300204328 | -150.407079 | 51.480311 | 0 | 3148.330566 | 3148.330566 | -9999.0 | 0 | 80 |
1 | BEAM0000 | 196830000300204329 | -150.406674 | 51.480271 | 0 | 3148.306885 | 3148.306885 | -9999.0 | 0 | 80 |
2 | BEAM0000 | 196830000300204330 | -150.406268 | 51.480231 | 0 | 3148.282959 | 3148.282959 | -9999.0 | 0 | 80 |
3 | BEAM0000 | 196830000300204331 | -150.405862 | 51.480191 | 0 | 3148.854736 | 3148.854736 | -9999.0 | 0 | 80 |
4 | BEAM0000 | 196830000300204332 | -150.405457 | 51.480151 | 0 | 3148.234863 | 3148.234863 | -9999.0 | 0 | 80 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
152101 | BEAM1011 | 196831100300353743 | -77.493929 | 0.424150 | 0 | -59.045544 | -59.045544 | -9999.0 | 0 | 0 |
152102 | BEAM1011 | 196831100300353744 | -77.493631 | 0.423730 | 0 | -59.179871 | -59.179871 | -9999.0 | 0 | 0 |
152103 | BEAM1011 | 196831100300353745 | -77.493332 | 0.423310 | 0 | -58.958637 | -58.958637 | -9999.0 | 0 | 0 |
152104 | BEAM1011 | 196831100300353746 | -77.493034 | 0.422891 | 0 | -59.209381 | -59.209381 | -9999.0 | 0 | 0 |
152105 | BEAM1011 | 196831100300353747 | -77.492735 | 0.422470 | 0 | -58.726070 | -58.726070 | -9999.0 | 0 | 0 |
1233557 rows × 10 columns
We can generate the data frame for all GEDI granules intersecting our region of interest.
= ['Date', 'Beam', 'Shot Number', 'Longitude', 'Latitude', 'Quality Flag',
columns'Canopy Elevation (m)','Elevation (m)', 'Plant Area Index', 'Canopy Height/rh100 (cm)' , 'Degrade Flag']
= pandas.DataFrame(columns=columns)
latslons_all
for f in gediFiles:
print(f)
= f.rsplit('_')[2]
date_str = datetime.strptime(date_str, '%Y%j%H%M%S').date().strftime("%m-%d-%Y")
date = h5py.File(f'{data_dir}{f}', 'r') # Read file using h5py
L2B for beamname in beamNames:
# Open the SDS
= L2B[f'{beamname}/geolocation/lat_lowestmode'][()]
lats = L2B[f'{beamname}/geolocation/lon_lowestmode'][()]
lons = L2B[f'{beamname}/geolocation/elev_lowestmode'][()]
elevs = L2B[f'{beamname}/geolocation/shot_number'][()].astype(str)
shots = L2B[f'{beamname}/l2b_quality_flag'][()]
quality = L2B[f'{beamname}/pai'][()]
pai = L2B[f'{beamname}/rh100'][()]
rh100 = L2B[f'{beamname}/geolocation/degrade_flag'][()]
degrade_flag = L2B[f'{beamname}/geolocation/elev_highestreturn'][()]
canopy
= pandas.DataFrame({'Date': date ,'Beam':beamname, 'Shot Number':shots, 'Longitude':lons, 'Latitude':lats, 'Quality Flag':quality,
latslons 'Canopy Elevation (m)':canopy, 'Elevation (m)':elevs, 'Plant Area Index':pai,
'Canopy Height/rh100 (cm)':rh100, 'Degrade Flag':degrade_flag})
= pandas.concat([latslons_all, latslons],join="inner")
latslons_all
del(lats, lons, elevs, shots, quality, pai, rh100, degrade_flag, canopy, latslons)
GEDI02_B_2022155015315_O19683_03_T05652_02_003_01_V002.h5
GEDI02_B_2022159001702_O19744_03_T08957_02_003_01_V002.h5
GEDI02_B_2022158145957_O19738_02_T03565_02_003_01_V002.h5
GEDI02_B_2022154163608_O19677_02_T01836_02_003_01_V002.h5
GEDI02_B_2022162224038_O19805_03_T06723_02_003_02_V002.h5
Create a list of geodataframe columns to be included as attributes in the output map
Plotting the entire sub-orbit for all granules will take a long time, and might include information that we do not need necessarily. So lets make a subset of data to only keep the data we need.
below, the shots that occured during a degraded period and low quality are removed from the dataframe.
= latslons_all [latslons_all ['Degrade Flag'] == 0].drop(columns = 'Degrade Flag')
latslons_all = latslons_all [latslons_all['Quality Flag'] == 1].drop(columns = 'Quality Flag')
latslons_all
latslons_all
Date | Beam | Shot Number | Longitude | Latitude | Canopy Elevation (m) | Elevation (m) | Plant Area Index | Canopy Height/rh100 (cm) | |
---|---|---|---|---|---|---|---|---|---|
105447 | 06-04-2022 | BEAM0000 | 196830000300309775 | -92.335071 | 20.843354 | -12.388881 | -14.957901 | 0.320302 | 255 |
105448 | 06-04-2022 | BEAM0000 | 196830000300309776 | -92.334736 | 20.842946 | -12.912969 | -15.556454 | 0.318079 | 264 |
105454 | 06-04-2022 | BEAM0000 | 196830000300309782 | -92.332736 | 20.840486 | -12.179410 | -15.567541 | 0.409812 | 338 |
105459 | 06-04-2022 | BEAM0000 | 196830000300309787 | -92.331073 | 20.838435 | -14.535298 | -16.880930 | 0.267779 | 233 |
105461 | 06-04-2022 | BEAM0000 | 196830000300309789 | -92.330405 | 20.837615 | -13.029422 | -15.300590 | 0.184147 | 226 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
146057 | 06-11-2022 | BEAM1011 | 198051100300346228 | -78.356099 | 4.286391 | 12.798177 | 10.115704 | 0.079636 | 268 |
146058 | 06-11-2022 | BEAM1011 | 198051100300346229 | -78.355801 | 4.285969 | 13.224768 | 10.095215 | 0.269218 | 311 |
146059 | 06-11-2022 | BEAM1011 | 198051100300346230 | -78.355503 | 4.285547 | 13.374081 | 11.324969 | 0.015392 | 203 |
150614 | 06-11-2022 | BEAM1011 | 198051100300350785 | -76.984106 | 2.347054 | 1283.832886 | 1276.046265 | 0.723939 | 778 |
150615 | 06-11-2022 | BEAM1011 | 198051100300350786 | -76.983813 | 2.346651 | 1271.422974 | 1256.035889 | 2.641645 | 1538 |
404288 rows × 9 columns
# reset the index and drop the NAs
= latslons_all.dropna()
latslons_all = latslons_all.reset_index(drop=True)
latslons_all latslons_all
Date | Beam | Shot Number | Longitude | Latitude | Canopy Elevation (m) | Elevation (m) | Plant Area Index | Canopy Height/rh100 (cm) | |
---|---|---|---|---|---|---|---|---|---|
0 | 06-04-2022 | BEAM0000 | 196830000300309775 | -92.335071 | 20.843354 | -12.388881 | -14.957901 | 0.320302 | 255 |
1 | 06-04-2022 | BEAM0000 | 196830000300309776 | -92.334736 | 20.842946 | -12.912969 | -15.556454 | 0.318079 | 264 |
2 | 06-04-2022 | BEAM0000 | 196830000300309782 | -92.332736 | 20.840486 | -12.179410 | -15.567541 | 0.409812 | 338 |
3 | 06-04-2022 | BEAM0000 | 196830000300309787 | -92.331073 | 20.838435 | -14.535298 | -16.880930 | 0.267779 | 233 |
4 | 06-04-2022 | BEAM0000 | 196830000300309789 | -92.330405 | 20.837615 | -13.029422 | -15.300590 | 0.184147 | 226 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
404283 | 06-11-2022 | BEAM1011 | 198051100300346228 | -78.356099 | 4.286391 | 12.798177 | 10.115704 | 0.079636 | 268 |
404284 | 06-11-2022 | BEAM1011 | 198051100300346229 | -78.355801 | 4.285969 | 13.224768 | 10.095215 | 0.269218 | 311 |
404285 | 06-11-2022 | BEAM1011 | 198051100300346230 | -78.355503 | 4.285547 | 13.374081 | 11.324969 | 0.015392 | 203 |
404286 | 06-11-2022 | BEAM1011 | 198051100300350785 | -76.984106 | 2.347054 | 1283.832886 | 1276.046265 | 0.723939 | 778 |
404287 | 06-11-2022 | BEAM1011 | 198051100300350786 | -76.983813 | 2.346651 | 1271.422974 | 1256.035889 | 2.641645 | 1538 |
404288 rows × 9 columns
5. Create a Geodataframe and Subset Spatially
Below, an additional column is created and called ‘geometry’ that contains a shapely
point generated from each lat/lon location from the shot is created. Next, the dataframe is converted to a Geopandas
GeoDataFrame.
# Take the lat/lon dataframe and convert each lat/lon to a shapely point and convert to a Geodataframe
= geopandas.GeoDataFrame(latslons_all, geometry=latslons_all.apply(lambda row: Point(row.Longitude, row.Latitude), axis=1))
latslons_all = latslons_all.set_crs('EPSG:4326') latslons_all
Import a GeoJSON of a section of Reserva de la Biósfera de Calakmul
National Forest as an additional GeoDataFrame.
= geopandas.GeoDataFrame.from_file(f'{data_dir}calakmul.geojson')
ROI = 'EPSG:4326' ROI.crs
'geometry'][0] ROI[
Next, filter the shots that are within the ROI boundaries.
= []
shot_list for num, geom in enumerate(latslons_all['geometry']):
if ROI.contains(geom)[0]:
= latslons_all.loc[num, 'Shot Number']
shot_n shot_list.append(shot_n)
= latslons_all.where(latslons_all['Shot Number'].isin(shot_list))
DF = DF.dropna().reset_index(drop=True) DF
DF
Date | Beam | Shot Number | Longitude | Latitude | Canopy Elevation (m) | Elevation (m) | Plant Area Index | Canopy Height/rh100 (cm) | geometry | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 06-04-2022 | BEAM0000 | 196830000300314188 | -90.882501 | 18.994573 | -1.029900 | -4.943680 | 0.099078 | 391 | POINT (-90.88250 18.99457) |
1 | 06-04-2022 | BEAM0000 | 196830000300314189 | -90.882217 | 18.994137 | 1.437216 | -4.340271 | 0.254931 | 576 | POINT (-90.88222 18.99414) |
2 | 06-04-2022 | BEAM0000 | 196830000300314190 | -90.881934 | 18.993701 | -0.111586 | -4.547207 | 0.081328 | 442 | POINT (-90.88193 18.99370) |
3 | 06-04-2022 | BEAM0000 | 196830000300314191 | -90.881651 | 18.993265 | 0.287704 | -4.408836 | 0.100879 | 469 | POINT (-90.88165 18.99326) |
4 | 06-04-2022 | BEAM0000 | 196830000300314192 | -90.881367 | 18.992827 | 0.891814 | -3.618357 | 0.039722 | 451 | POINT (-90.88137 18.99283) |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
26121 | 06-11-2022 | BEAM1011 | 198051100300312342 | -89.001523 | 18.442686 | 169.125259 | 150.570358 | 2.720562 | 1854 | POINT (-89.00152 18.44269) |
26122 | 06-11-2022 | BEAM1011 | 198051100300312343 | -89.001190 | 18.442281 | 154.575348 | 149.321854 | 0.006572 | 525 | POINT (-89.00119 18.44228) |
26123 | 06-11-2022 | BEAM1011 | 198051100300312344 | -89.000857 | 18.441875 | 154.223221 | 148.857941 | 0.101806 | 536 | POINT (-89.00086 18.44187) |
26124 | 06-11-2022 | BEAM1011 | 198051100300312345 | -89.000526 | 18.441474 | 157.639175 | 142.810150 | 4.159529 | 1481 | POINT (-89.00053 18.44147) |
26125 | 06-11-2022 | BEAM1011 | 198051100300312346 | -89.000191 | 18.441063 | 153.560394 | 147.859802 | 0.053789 | 569 | POINT (-89.00019 18.44106) |
26126 rows × 10 columns
= geopandas.GeoDataFrame(DF).drop(columns=['Longitude', 'Latitude']) All_DF
6. Visualize a GeoDataFrame
In this section, the GeoDataFrame and the geoviews
python package are used to spatially visualize the location of the GEDI shots on a basemap layer and import a GeoJSON file of the spatial region of interest for this use case example.
Defining the vdims below will allow you to hover over specific shots and view information about them.
# Create a list of geodataframe columns to be included as attributes in the output map
= []
vdims for f in All_DF:
if f not in ['geometry']:
vdims.append(f)
vdims
['Date',
'Beam',
'Shot Number',
'Canopy Elevation (m)',
'Elevation (m)',
'Plant Area Index',
'Canopy Height/rh100 (cm)']
# Define a function for visualizing GEDI points
def pointVisual(features, vdims):
return (gvts.EsriImagery * geoviews.Points(features, vdims=vdims).options(tools=['hover'], height=500, width=900, size=4,
='yellow', fontsize={'xticks': 10, 'yticks': 10,
color'xlabel':16, 'ylabel': 16}))
# Visualize GEDI data
'geometry']).opts(line_color='red', color=None)* pointVisual(All_DF, vdims = vdims) geoviews.Polygons(ROI[
7. Export Subsets as GeoJSON Files
Finally, export the GeoDataFrame as a .geojson
file that can be easily opened in your favorite remote sensing and/or GIS software and will include an attribute table with all of the shots/values for each of the SDS layers in the dataframe.
= f'{data_dir}GEDI02_B_Calakmul.geojson' # Create an output file name using the input file name
outName print(outName)
='GeoJSON') # Export to GeoJSON All_DF.to_file(outName, driver
/home/jovyan/shared/2023SSC/GEDI02_B_Calakmul.geojson
Helpful Links
- LP DAAC Website
- LP DAAC GitHub
- GEDI Data Resources GitHub
- GEDI Data Product Pages
- University of Maryland GEDI - Learn more about the GEDI Mission
- OpenAltimetry - Learn about GEDI coverage
- NASA Earthdata Search
Contact Info:
Email: LPDAAC@usgs.gov
Voice: +1-866-573-3222
Organization: Land Processes Distributed Active Archive Center (LP DAAC)¹
Website: https://lpdaac.usgs.gov/
Date last modified: 11-15-2023
¹Work performed under USGS contract G15PD00467 for NASA contract NNG14HH33I.