Accessing the MAAP CMR STAC with R

Authors: Harshini Girish (UAH), Sheyenne Kirkland (UAH), Alex Mandel (DevSeed), Henry Rodman (DevSeed)

Date: December 13, 2024

Description: In this notebook, we’ll use rstac to search for collections and associated items within the MAAP STAC Catalog.

Run This Notebook

To access and run this tutorial within MAAP’s Algorithm Development Environment (ADE), please refer to the “Getting started with the MAAP” section of our documentation.

Disclaimer: it is highly recommended to run a tutorial within MAAP’s ADE, which already includes packages specific to MAAP, such as maap-py. Running the tutorial outside of the MAAP ADE may lead to errors. Users should work within the “R/Python” workspace.

Additional Resources

## Install/Load Packages

Let’s install and load the packages necessary for this tutorial.

[ ]:
install.packages("rstac")

library(rstac)

Initializing the MAAP STAC Endpoint

Before beginning, we’ll form a connection to the MAAP STAC endpoint to set up and inspect the STAC endpoint for querying geospatial data.

[224]:
# Define the MAAP STAC endpoint
stac_endpoint <- stac("https://stac.maap-project.org/")

# Display the STAC endpoint metadata
cat("STAC Endpoint Metadata:\n")
print(stac_endpoint)
STAC Endpoint Metadata:
###rstac_query
- url: https://stac.maap-project.org/
- params:
- field(s): version, base_url, endpoint, params, verb, encode

Fetching and Displaying STAC Collections

This code fetches and displays collections from a STAC (SpatioTemporal Asset Catalog) endpoint. It extracts id and title for each collection for further exploration or querying.

[225]:
collections <- stac_endpoint |>
    collections() |>
    get_request()
# Ensure collections are retrieved
if (length(collections$collections) > 0) {
    # Extract collection IDs and titles
    collection_info <- lapply(collections$collections, function(x) {
        list(id = x$id, title = x$title)
    })
    # Display the collection information
    for (i in seq_along(collection_info)) {
        cat("Collection ID:", collection_info[[i]]$id, "\n")
        cat("Title:", collection_info[[i]]$title, "\n\n")
    }
} else {
    cat("No collections found or error retrieving collections.\n")
}
Collection ID: Landsat8_SurfaceReflectance
Title: Landsat 8 Operational Land Imager (OLI) Surface Reflectance Analysis Ready Data (ARD) V1, Peru and Equatorial Western Africa, April 2013-January 2020

Collection ID: Global_PALSAR2_PALSAR_FNF
Title: Global 25m Resolution PALSAR-2/PALSAR Forest/Non-Forest Map

Collection ID: Global_Forest_Change_2000-2017
Title: Global Forest Change 2000-2017

Collection ID: AFRISAR_DLR2
Title: AFRISAR_DLR2

Collection ID: GlobCover_09
Title: GlobCover Global Land Cover Product (2009)

Collection ID: AfriSAR_UAVSAR_KZ
Title: AfriSAR UAVSAR Vertical Wavenumber (KZ) Generated Using NISAR Tools

Collection ID: AfriSAR_UAVSAR_Ungeocoded_Covariance
Title: AfriSAR UAVSAR Ungeocoded Covariance Matrix product Generated Using NISAR Tools

Collection ID: AfriSAR_UAVSAR_Normalization_Area
Title: AfriSAR UAVSAR Normalization Area Generated Using NISAR Tools

Collection ID: AfriSAR_UAVSAR_Geocoded_SLC
Title: AfriSAR UAVSAR Geocoded SLCs Generated Using NISAR Tools

Collection ID: AfriSAR_UAVSAR_Geocoded_Covariance
Title: AfriSAR UAVSAR Geocoded Covariance Matrix product Generated Using NISAR Tools

Collection ID: GlobCover_05_06
Title: GlobCover Global Land Cover Product (2005-06)

Collection ID: GEDI_CalVal_Field_Data
Title: Global Ecosystem Dynamics Investigation (GEDI) Calibration/Validation Field Survey Dataset

Collection ID: AfriSAR_UAVSAR_Coreg_SLC
Title: AfriSAR UAVSAR Coregistered SLCs Generated Using NISAR Tools

Collection ID: GEDI_CalVal_Lidar_Data_Compressed
Title: Global Ecosystem Dynamics Investigation (GEDI) Calibration/Validation Airborne Lidar Dataset (Compressed)

Collection ID: ABoVE_UAVSAR_PALSAR
Title: Arctic-Boreal Vulnerability Experiment Uninhabited Aerial Vehicle Synthetic Aperture Radar Polarimetric SAR

Collection ID: AFRISAR_DLR
Title: AFRISAR_DLR

Collection ID: BIOSAR1
Title: BIOSAR1

Collection ID: GEDI_CalVal_Lidar_Data
Title: Global Ecosystem Dynamics Investigation (GEDI) Calibration/Validation Airborne Lidar Dataset

Collection ID: ICESat2_Boreal_AGB_tindex_average
Title: ICESat2-Boreal Above Ground Biomass T-Index Average

Collection ID: Paraguay_Country_Pilot
Title: Paraguay Country Pilot

Collection ID: ESACCI_Biomass_L4_AGB_V4_100m
Title: ESA CCI Above-Ground Biomass Product Level 4 Version 4

Collection ID: NCEO_Africa_AGB_100m_2017
Title: National Centre for Eath Oberservation (NCEO) Africa Aboveground Woody Biomass (AGB) 2017

Collection ID: SRTMGL1_COD
Title: NASA Shuttle Radar Topography Mission Global 1

Collection ID: GEDI_CalVal_Lidar_COPC
Title: GEDI CalVal Lidar COPC

Collection ID: icesat2-boreal
Title: Gridded Boreal Aboveground Biomass Density c.2020 at 30m resolution

Collection ID: nisar-sim
Title: Simulated NISAR

Collection ID: glad-glclu2020-v2
Title: GLAD: Annual maps of land cover and land use

Collection ID: glad-glclu2020-change-v2
Title: GLAD: Net change of land cover and land use between 2000 and 2020

Assigning and Selecting a STAC Collection ID

This code selects a collection ID from the list of collections retrieved from the STAC catalog. It selects a single collection ID from the fetched collections.

[226]:
# Assign collection ID
if (length(collections$collections) > 0) {
    # Choose a specific collection (21st in this example)
    collection_id <- collections$collections[[21]]$id
    cat("Selected Collection ID:", collection_id, "\n")
} else {
    stop("No collections found.")
}
Selected Collection ID: ESACCI_Biomass_L4_AGB_V4_100m

Searching and Retrieving Items from a STAC Collection

This code searches for items in the selected STAC collection using the stac_search() function. It safely handles errors during the query and retrieves the items, printing details such as item IDs, dates, and associated links. If no items are found, it outputs a message indicating so.

[227]:
# Fetch items
items <- stac_endpoint |>
    stac_search(collections = collection_id) |>
    get_request()
# Print the retrieved items
print(items)
# Process and display item information
if (length(items$features) > 0) {
    cat("Found", length(items$features), "items:\n\n")
    # Display details of the first few items
    for (i in seq_len(min(5, length(items$features)))) {
        item <- items$features[[i]]
        cat("Item ID:", item$id, "\n")
        cat("Date:", item$properties$datetime, "\n")
        cat("Links:", paste(sapply(item$links, function(x) x$href), collapse = ", "), "\n\n")
    }
} else {
    cat("No items found for collection:", collection_id, "\n")
}
###Items
- features (10 item(s)):
  - S50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S50W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S50W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S50W040_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S50E070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S50E060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S40W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S40W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S40E170_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
  - S40E160_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
- assets: estimates, standard_deviation
- item's fields:
assets, bbox, collection, geometry, id, links, properties, stac_extensions, stac_version, type
Found 10 items:

Item ID: S50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
Date: 2020-01-01T00:00:00+00:00
Links: NULL, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m/items/S50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0

Item ID: S50W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
Date: 2020-01-01T00:00:00+00:00
Links: NULL, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m/items/S50W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0

Item ID: S50W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
Date: 2020-01-01T00:00:00+00:00
Links: NULL, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m/items/S50W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0

Item ID: S50W040_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
Date: 2020-01-01T00:00:00+00:00
Links: NULL, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m/items/S50W040_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0

Item ID: S50E070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
Date: 2020-01-01T00:00:00+00:00
Links: NULL, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m, https://stac.maap-project.org/, https://stac.maap-project.org/collections/ESACCI_Biomass_L4_AGB_V4_100m/items/S50E070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0

Extracting and Displaying Assets from a STAC Item

This code extracts the assets (downloadable data resources) from the first item in the STAC search results.

[228]:
if (length(items$features) > 0) {
    # Extract and display the first item's assets
    first_item <- items$features[[1]]
    assets <- first_item$assets
    print(first_item)
    cat("Available assets:\n")
    print(names(assets))  # List of asset types
} else {
    cat("No items found for collection:", collection_id, "\n")
}
###Item
- id: S50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0
- collection: ESACCI_Biomass_L4_AGB_V4_100m
- bbox:
xmin: -80.00000, ymin: -60.00000, xmax: -70.00000, ymax: -50.00000
- datetime: 2020-01-01T00:00:00+00:00
- assets: estimates, standard_deviation
- item's fields:
assets, bbox, collection, geometry, id, links, properties, stac_extensions, stac_version, type
Available assets:
[1] "estimates"          "standard_deviation"

Listing and Displaying Asset URLs from a STAC Item

This loop iterates through all available assets in the STAC item and prints each asset’s name and its corresponding URL.

[229]:
for (asset_name in names(assets)) {
    cat("Asset:", asset_name, "\n")
    cat("URL:", assets[[asset_name]]$href, "\n\n")
}
Asset: estimates
URL: s3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif

Asset: standard_deviation
URL: s3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S50W080_ESACCI-BIOMASS-L4-AGB_SD-MERGED-100m-2020-fv4.0.tif

Performing a Focused Search Using the MAAP STAC API

This code performs a search query and retrieves items from the MAAP STAC. The search is configured with the following parameters:

Collection: Specifies the dataset to search within.

Temporal Range: Filters items within a specific date range.

Bounding Box: Spatially filters items to a defined area of interest.

[230]:
datetime <- "2020-01-01T00:00:00Z/2020-01-31T23:59:59Z"   # YYYY-MM-DDTHH:MM:SSZ/YYYY-MM-DDTHH:MM:SSZ
bbox <- c(-74,-57,-18,-5.8)

stac_query <- stac(
    stac_endpoint[[2]]
)|>
  stac_search(
    collections = collection_id,
    bbox = bbox,
    datetime = datetime
  ) |>
  get_request()

#stac_query

results <- lapply(
  stac_query$features,
  \(x) data.frame(collection = x$collection, id = x$id, datetime = x$properties$datetime, desc = x$assets$estimates$description)
) |>
  do.call(what = rbind)

results
A data.frame: 10 × 4
collectioniddatetimedesc
<chr><chr><chr><chr>
ESACCI_Biomass_L4_AGB_V4_100mS50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS50W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS50W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS50W040_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS40W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS40W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS30W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS30W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS30W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates
ESACCI_Biomass_L4_AGB_V4_100mS20W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.02020-01-01T00:00:00+00:00Cloud Optimized GeoTIFF of AGB estimates

Additionally, we can create a list of hrefs for the COGs (cloud-optimized geotiffs) with the AGB (above-ground biomass) estimates. These are gathered from our focused search in the cell above.

[231]:
# get urls
s3_urls = sapply(stac_query$features, function(x) {x$assets$estimates$href})
s3_urls
  1. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S50W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  2. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S50W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  3. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S50W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  4. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S50W040_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  5. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S40W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  6. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S40W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  7. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S30W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  8. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S30W070_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  9. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S30W060_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'
  10. 's3://nasa-maap-data-store/file-staging/nasa-map/ESACCI_Biomass_L4_AGB_V4_100m_2020/S20W080_ESACCI-BIOMASS-L4-AGB-MERGED-100m-2020-fv4.0.tif'