diff --git a/nisar_biomass/NISAR, BIOMASS & GEDI.ipynb b/nisar_biomass/NISAR, BIOMASS & GEDI.ipynb new file mode 100644 index 0000000..03eb93c --- /dev/null +++ b/nisar_biomass/NISAR, BIOMASS & GEDI.ipynb @@ -0,0 +1,1261 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "92563beb-f857-4547-9a20-27c1ca0a6407", + "metadata": {}, + "source": [ + "# GEDI, BIOMASS, and NISAR: Visualization for an AOI" + ] + }, + { + "cell_type": "markdown", + "id": "1f0131d2-5059-4841-8ca6-4d05a3375b11", + "metadata": {}, + "source": [ + "**Date:** March 2nd, 2026\n", + "\n", + "**Author**: Harshini Girish(UAH), Alex Mandel(Development Seed), Henry Rodman(Development Seed), Chuck Daniels(Development Seed)\n", + "\n", + "\n", + "**Description**:This notebook demonstrates a lightweight, map-first workflow for visualizing where three Earth observation datasets overlap for a given Area of Interest (AOI). We begin by importing required libraries, loading the AOI geometry (sites polygon layer), ensuring it is in WGS84 (EPSG:4326), and computing both a tight AOI bounding box and a buffered bounding box for data discovery. Using a single STAC helper function, we then perform bounding-box searches for NISAR, ESA BIOMASS, and GEDI collections from their respective STAC catalogs and convert the returned STAC items into GeoDataFrames for mapping. Finally, we render an interactive Folium map that first previews the AOI polygon and then overlays the three datasets as separate, color-coded layers with a layer control, enabling quick visual inspection of coverage and overlap before any downstream subsetting or analysis." + ] + }, + { + "cell_type": "markdown", + "id": "ca1e0d9e-3e5b-4cfa-b0cf-a1d2040a2dcb", + "metadata": {}, + "source": [ + "## Run This Notebook\n", + "\n", + "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.\n", + "\n", + "**Disclaimer**: It is highly recommended to run this 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.\n" + ] + }, + { + "cell_type": "markdown", + "id": "bc45e1a4-862a-488d-bca8-d6d78364f4b9", + "metadata": {}, + "source": [ + "## Install/Import Packages\n", + " \n", + "Let's install and load the packages necessary for this tutorial." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "038cced6-b2d8-4975-a2ed-57ed29347450", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from shapely.geometry import box, mapping, Point\n", + "import pandas as pd\n", + "import geopandas as gpd\n", + "import folium\n", + "\n", + "import pystac_client\n", + "from pystac import ItemCollection" + ] + }, + { + "cell_type": "markdown", + "id": "c1d55648-869c-4914-aeb0-53fb9e662d3f", + "metadata": {}, + "source": [ + "## Inputs \n", + "Edit these paths/parameters to match your AOI and the collections you want to check." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "11741cb7-41db-436d-ad91-a9e923b9c11f", + "metadata": {}, + "outputs": [], + "source": [ + "# --- AOI / Sites input (KML/GeoJSON/Shapefile/etc.) ---\n", + "SITES_PATH = \"amacayacu_100m.kml\" # change if needed\n", + "SITE_ID_COL = None # set to an existing column name, or leave None to auto-create site_id\n", + "\n", + "# --- STAC endpoints ---\n", + "NISAR_STAC_URL = \"https://cmr.earthdata.nasa.gov/stac/ASF\"\n", + "BIOMASS_STAC_URL = \"https://catalog.maap.eo.esa.int/catalogue/\"\n", + "GEDI_STAC_URL = \"https://cmr.earthdata.nasa.gov/stac/ORNL_CLOUD\"\n", + "\n", + "# --- Collections (use exact STAC collection IDs) ---\n", + "NISAR_COLLECTION = \"NISAR_L2_GCOV_BETA_V1_1\"\n", + "BIOMASS_COLLECTIONS = [\"BiomassLevel1b\"]\n", + "GEDI_COLLECTION = \"GEDI_L4A_AGB_Density_V2_1_2056_2.1\"\n", + "\n", + "# --- Optional datetime filters (ISO8601 interval), or None ---\n", + "NISAR_DT = None\n", + "BIOMASS_DT = None\n", + "GEDI_DT = None\n", + "\n", + "# --- Buffer for discovery/search (degrees; EPSG:4326 lon/lat) ---\n", + "BBOX_BUFFER_DEG = 0.25\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "054970c6-ef0b-4783-81c7-9eb24c110805", + "metadata": {}, + "source": [ + "## Load AOI / sites and compute bbox \n", + "We read the sites file into a GeoDataFrame (EPSG:4326), ensure a `site_id`, and compute the AOI bbox for catalog searches." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d777bc06-1490-4e2f-a6a7-780e1ecd25ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "AOI bbox: (-70.2926180592577, -3.81826995097037, -70.2404260082027, -3.78652050791343)\n", + "Buffered bbox: (-70.5426180592577, -4.06826995097037, -69.9904260082027, -3.53652050791343)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
site_idgeometry
0site_1MULTIPOLYGON (((-70.29262 -3.7921, -70.29262 -...
\n", + "
" + ], + "text/plain": [ + " site_id geometry\n", + "0 site_1 MULTIPOLYGON (((-70.29262 -3.7921, -70.29262 -..." + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sites_gdf = gpd.read_file(SITES_PATH)\n", + "\n", + "# Ensure WGS84 lon/lat\n", + "if sites_gdf.crs is None:\n", + " sites_gdf = sites_gdf.set_crs(\"EPSG:4326\")\n", + "else:\n", + " sites_gdf = sites_gdf.to_crs(\"EPSG:4326\")\n", + "\n", + "# Ensure a site_id column\n", + "if SITE_ID_COL and SITE_ID_COL in sites_gdf.columns:\n", + " sites_gdf = sites_gdf.rename(columns={SITE_ID_COL: \"site_id\"})\n", + "elif \"site_id\" not in sites_gdf.columns:\n", + " sites_gdf[\"site_id\"] = [f\"site_{i+1}\" for i in range(len(sites_gdf))]\n", + "\n", + "aoi_geom = sites_gdf.geometry.union_all()\n", + "minx, miny, maxx, maxy = aoi_geom.bounds\n", + "BBOX = (minx, miny, maxx, maxy)\n", + "\n", + "# buffered bbox for discovery\n", + "buf = BBOX_BUFFER_DEG\n", + "BBOX_BUF = (minx-buf, miny-buf, maxx+buf, maxy+buf)\n", + "\n", + "print(\"AOI bbox:\", BBOX)\n", + "print(\"Buffered bbox:\", BBOX_BUF)\n", + "sites_gdf[[\"site_id\", \"geometry\"]].head()\n" + ] + }, + { + "cell_type": "markdown", + "id": "cc34cbe5-39c9-40a2-ab8c-3df637f351f0", + "metadata": {}, + "source": [ + "## AOI preview map\n", + "Visualize the AOI polygons before running any STAC searches." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "938ff8b8-f786-4293-8fd5-ee54ca3b09d4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Quick AOI preview map (sites + AOI outline)\n", + "\n", + "aoi_map = folium.Map(\n", + " location=[(miny + maxy) / 2, (minx + maxx) / 2],\n", + " zoom_start=10,\n", + " tiles=\"OpenStreetMap\",\n", + ")\n", + "\n", + "# Site polygons (purple)\n", + "folium.GeoJson(\n", + " sites_gdf,\n", + " name=\"Sites\",\n", + " style_function=lambda _: {\"color\": \"purple\", \"weight\": 2, \"fillOpacity\": 0.10},\n", + ").add_to(aoi_map)\n", + "\n", + "# AOI outline (red)\n", + "folium.GeoJson(\n", + " data={\"type\": \"Feature\", \"geometry\": mapping(aoi_geom), \"properties\": {\"name\": \"AOI\"}},\n", + " name=\"AOI\",\n", + " style_function=lambda _: {\"color\": \"red\", \"weight\": 3, \"fillOpacity\": 0.0},\n", + ").add_to(aoi_map)\n", + "\n", + "folium.LayerControl(collapsed=False).add_to(aoi_map)\n", + "aoi_map\n" + ] + }, + { + "cell_type": "markdown", + "id": "41fdea40-ba12-4d7c-878f-e84687377189", + "metadata": {}, + "source": [ + "## STAC helper\n", + "\n", + "Single helper to run a STAC bbox search and directly return a GeoDataFrame for mapping." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6a6a5675-7f84-4b6b-86be-ed6faa4d686c", + "metadata": {}, + "outputs": [], + "source": [ + "def stac_search_to_gdf(catalog_url, collections, bbox, datetime=None, limit=200):\n", + " \"\"\"Run a STAC bbox search and return results as a GeoDataFrame (EPSG:4326).\"\"\"\n", + " cat = pystac_client.Client.open(catalog_url)\n", + " search = cat.search(collections=collections, bbox=bbox, datetime=datetime, max_items=limit)\n", + " items = list(search.items())\n", + " return gpd.GeoDataFrame.from_features([it.to_dict() for it in items], crs=\"EPSG:4326\")\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "ca24fae4-5fde-452c-89a3-d8abb0ffbeac", + "metadata": {}, + "source": [ + "## NISAR coverage\n", + "Search the NISAR STAC catalog for the chosen NISAR collection intersecting the AOI bbox." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "474de714-4718-4b70-ade0-be617b4ab667", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NISAR items found for NISAR_L2_GCOV_BETA_V1_1: 9\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
geometrydatetimestorage:schemesstart_datetimeend_datetime
0POLYGON ((-69.99474 -3.94381, -70.45989 -1.795...2025-11-06T10:27:57Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2025-11-06T10:27:57.000Z2025-11-06T10:28:32.999Z
1POLYGON ((-67.8897 -3.94315, -68.34109 -1.8547...2025-11-11T10:19:38Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2025-11-11T10:19:38.000Z2025-11-11T10:20:12.999Z
2POLYGON ((-70.35039 -1.73374, -70.81558 -3.881...2025-11-30T22:58:08Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2025-11-30T22:58:08.000Z2025-11-30T22:58:43.999Z
3POLYGON ((-67.89068 -3.93366, -68.34215 -1.845...2025-12-05T10:19:39Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2025-12-05T10:19:39.000Z2025-12-05T10:20:13.999Z
4POLYGON ((-69.98483 -3.99241, -70.4499 -1.8445...2025-12-12T10:27:58Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2025-12-12T10:27:58.000Z2025-12-12T10:28:33.999Z
\n", + "
" + ], + "text/plain": [ + " geometry datetime \\\n", + "0 POLYGON ((-69.99474 -3.94381, -70.45989 -1.795... 2025-11-06T10:27:57Z \n", + "1 POLYGON ((-67.8897 -3.94315, -68.34109 -1.8547... 2025-11-11T10:19:38Z \n", + "2 POLYGON ((-70.35039 -1.73374, -70.81558 -3.881... 2025-11-30T22:58:08Z \n", + "3 POLYGON ((-67.89068 -3.93366, -68.34215 -1.845... 2025-12-05T10:19:39Z \n", + "4 POLYGON ((-69.98483 -3.99241, -70.4499 -1.8445... 2025-12-12T10:27:58Z \n", + "\n", + " storage:schemes \\\n", + "0 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "1 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "2 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "3 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "4 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "\n", + " start_datetime end_datetime \n", + "0 2025-11-06T10:27:57.000Z 2025-11-06T10:28:32.999Z \n", + "1 2025-11-11T10:19:38.000Z 2025-11-11T10:20:12.999Z \n", + "2 2025-11-30T22:58:08.000Z 2025-11-30T22:58:43.999Z \n", + "3 2025-12-05T10:19:39.000Z 2025-12-05T10:20:13.999Z \n", + "4 2025-12-12T10:27:58.000Z 2025-12-12T10:28:33.999Z " + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nisar_gdf = stac_search_to_gdf(\n", + " catalog_url=NISAR_STAC_URL,\n", + " collections=[NISAR_COLLECTION],\n", + " bbox=BBOX,\n", + " datetime=NISAR_DT,\n", + " limit=500,\n", + ")\n", + "print(f\"NISAR items found for {NISAR_COLLECTION}: {len(nisar_gdf)}\")\n", + "nisar_gdf.head()\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "4dad8088-fa80-4f96-bed6-3eb4c2690eb3", + "metadata": {}, + "source": [ + "## BIOMASS coverage\n", + "Search the ESA BIOMASS STAC catalog for the chosen BIOMASS collection(s) intersecting the AOI bbox." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "6d2acbe9-bd83-427d-98e1-29ef4f491cfc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BIOMASS items found (['BiomassLevel1b']): 7\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
geometryeofeos:repeat_cycle_idstart_datetimeend_datetimeprocessing:facilityproduct:typeeofeos:global_coverage_idsat:anx_datetimetitleplatform...sar:observation_directionsar:polarizationsauth:schemessar:instrument_modeeofeos:orbit_drift_flagprocessing:datetimeeofeos:mission_phaseupdatedsat:absolute_orbitproduct:acquisition_type
0POLYGON ((-70.63902 -4.03723, -70.09614 -4.150...42026-02-20T22:49:07.442Z2026-02-20T22:49:27.731ZBiomass CPFS1_DGM__1S12026-02-20T21:59:28.073ZBIO_S1_DGM__1S_20260220T224907_20260220T224927...Biomass...left[HH, HV, VH, VV]{'s3': {'type': 's3'}, 'oidc': {'openIdConnect...SMFalse2026-02-21T10:04:09ZTOMOGRAPHIC2026-02-27T14:23:39Z4365nominal
1POLYGON ((-70.64701 -4.03701, -70.10399 -4.150...52026-02-23T22:49:09.093Z2026-02-23T22:49:29.382ZBiomass CPFS1_DGM__1S12026-02-23T21:59:29.731ZBIO_S1_DGM__1S_20260223T224909_20260223T224929...Biomass...left[HH, HV, VH, VV]{'s3': {'type': 's3'}, 'oidc': {'openIdConnect...SMFalse2026-02-24T11:00:18ZTOMOGRAPHIC2026-02-27T14:28:20Z4409nominal
2POLYGON ((-70.66071 -4.03709, -70.11783 -4.150...72026-03-01T22:49:12.783Z2026-03-01T22:49:33.071ZBiomass CPFS1_DGM__1S12026-03-01T21:59:33.396ZBIO_S1_DGM__1S_20260301T224912_20260301T224933...Biomass...left[HH, HV, VH, VV]{'s3': {'type': 's3'}, 'oidc': {'openIdConnect...SMFalse2026-03-02T11:02:12ZTOMOGRAPHIC2026-03-02T13:01:34Z4497nominal
3POLYGON ((-70.62412 -4.03726, -70.08149 -4.150...22026-02-14T22:49:03.840Z2026-02-14T22:49:24.128ZBiomass CPFS1_DGM__1S12026-02-14T21:59:24.479ZBIO_S1_DGM__1S_20260214T224903_20260214T224924...Biomass...left[HH, HV, VH, VV]{'s3': {'type': 's3'}, 'oidc': {'openIdConnect...SMFalse2026-02-15T10:26:08ZTOMOGRAPHIC2026-02-27T14:14:10Z4277nominal
4POLYGON ((-70.6162 -4.03741, -70.07372 -4.1507...12026-02-11T22:49:02.000Z2026-02-11T22:49:22.289ZBiomass CPFS1_DGM__1S12026-02-11T21:59:22.648ZBIO_S1_DGM__1S_20260211T224902_20260211T224922...Biomass...left[HH, HV, VH, VV]{'s3': {'type': 's3'}, 'oidc': {'openIdConnect...SMFalse2026-02-12T10:02:06ZTOMOGRAPHIC2026-02-27T14:09:30Z4233nominal
\n", + "

5 rows × 35 columns

\n", + "
" + ], + "text/plain": [ + " geometry eofeos:repeat_cycle_id \\\n", + "0 POLYGON ((-70.63902 -4.03723, -70.09614 -4.150... 4 \n", + "1 POLYGON ((-70.64701 -4.03701, -70.10399 -4.150... 5 \n", + "2 POLYGON ((-70.66071 -4.03709, -70.11783 -4.150... 7 \n", + "3 POLYGON ((-70.62412 -4.03726, -70.08149 -4.150... 2 \n", + "4 POLYGON ((-70.6162 -4.03741, -70.07372 -4.1507... 1 \n", + "\n", + " start_datetime end_datetime processing:facility \\\n", + "0 2026-02-20T22:49:07.442Z 2026-02-20T22:49:27.731Z Biomass CPF \n", + "1 2026-02-23T22:49:09.093Z 2026-02-23T22:49:29.382Z Biomass CPF \n", + "2 2026-03-01T22:49:12.783Z 2026-03-01T22:49:33.071Z Biomass CPF \n", + "3 2026-02-14T22:49:03.840Z 2026-02-14T22:49:24.128Z Biomass CPF \n", + "4 2026-02-11T22:49:02.000Z 2026-02-11T22:49:22.289Z Biomass CPF \n", + "\n", + " product:type eofeos:global_coverage_id sat:anx_datetime \\\n", + "0 S1_DGM__1S 1 2026-02-20T21:59:28.073Z \n", + "1 S1_DGM__1S 1 2026-02-23T21:59:29.731Z \n", + "2 S1_DGM__1S 1 2026-03-01T21:59:33.396Z \n", + "3 S1_DGM__1S 1 2026-02-14T21:59:24.479Z \n", + "4 S1_DGM__1S 1 2026-02-11T21:59:22.648Z \n", + "\n", + " title platform ... \\\n", + "0 BIO_S1_DGM__1S_20260220T224907_20260220T224927... Biomass ... \n", + "1 BIO_S1_DGM__1S_20260223T224909_20260223T224929... Biomass ... \n", + "2 BIO_S1_DGM__1S_20260301T224912_20260301T224933... Biomass ... \n", + "3 BIO_S1_DGM__1S_20260214T224903_20260214T224924... Biomass ... \n", + "4 BIO_S1_DGM__1S_20260211T224902_20260211T224922... Biomass ... \n", + "\n", + " sar:observation_direction sar:polarizations \\\n", + "0 left [HH, HV, VH, VV] \n", + "1 left [HH, HV, VH, VV] \n", + "2 left [HH, HV, VH, VV] \n", + "3 left [HH, HV, VH, VV] \n", + "4 left [HH, HV, VH, VV] \n", + "\n", + " auth:schemes sar:instrument_mode \\\n", + "0 {'s3': {'type': 's3'}, 'oidc': {'openIdConnect... SM \n", + "1 {'s3': {'type': 's3'}, 'oidc': {'openIdConnect... SM \n", + "2 {'s3': {'type': 's3'}, 'oidc': {'openIdConnect... SM \n", + "3 {'s3': {'type': 's3'}, 'oidc': {'openIdConnect... SM \n", + "4 {'s3': {'type': 's3'}, 'oidc': {'openIdConnect... SM \n", + "\n", + " eofeos:orbit_drift_flag processing:datetime eofeos:mission_phase \\\n", + "0 False 2026-02-21T10:04:09Z TOMOGRAPHIC \n", + "1 False 2026-02-24T11:00:18Z TOMOGRAPHIC \n", + "2 False 2026-03-02T11:02:12Z TOMOGRAPHIC \n", + "3 False 2026-02-15T10:26:08Z TOMOGRAPHIC \n", + "4 False 2026-02-12T10:02:06Z TOMOGRAPHIC \n", + "\n", + " updated sat:absolute_orbit product:acquisition_type \n", + "0 2026-02-27T14:23:39Z 4365 nominal \n", + "1 2026-02-27T14:28:20Z 4409 nominal \n", + "2 2026-03-02T13:01:34Z 4497 nominal \n", + "3 2026-02-27T14:14:10Z 4277 nominal \n", + "4 2026-02-27T14:09:30Z 4233 nominal \n", + "\n", + "[5 rows x 35 columns]" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "biomass_gdf = stac_search_to_gdf(\n", + " catalog_url=BIOMASS_STAC_URL,\n", + " collections=BIOMASS_COLLECTIONS,\n", + " bbox=BBOX,\n", + " datetime=BIOMASS_DT,\n", + " limit=500,\n", + ")\n", + "print(f\"BIOMASS items found ({BIOMASS_COLLECTIONS}): {len(biomass_gdf)}\")\n", + "biomass_gdf.head()\n" + ] + }, + { + "cell_type": "markdown", + "id": "110ce4ab-5aa8-46b7-8398-c85185a090ac", + "metadata": {}, + "source": [ + "## GEDI coverage\n", + "Search the GEDI STAC catalog for GEDI L4A AGBD intersecting the buffered AOI bbox (GEDI tracks can be sparse)." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "80fcde43-f814-4693-8d8e-16e0d0982592", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "GEDI items found for GEDI_L4A_AGB_Density_V2_1_2056_2.1: 138\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
geometrydatetimestorage:schemesstart_datetimeend_datetime
0POLYGON ((-90.92339 -28.63784, -88.13659 -25.8...2019-04-20T09:42:53Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2019-04-20T09:42:53.000Z2019-04-20T09:52:33.000Z
1POLYGON ((-72.56963 -0.28696, -70.40899 -3.350...2019-05-17T11:26:30Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2019-05-17T11:26:30.000Z2019-05-17T11:36:36.000Z
2POLYGON ((-73.19654 -0.02675, -71.0381 -3.0880...2019-05-24T08:44:16Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2019-05-24T08:44:16.000Z2019-05-24T08:54:31.000Z
3POLYGON ((-90.70751 -29.22035, -87.8886 -26.44...2019-06-12T12:34:08Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2019-06-12T12:34:08.000Z2019-06-12T12:44:00.000Z
4POLYGON ((-72.85289 -0.06564, -70.69566 -3.124...2019-06-18T22:34:32Z{'aws': {'type': 'aws-s3', 'platform': 'https:...2019-06-18T22:34:32.000Z2019-06-18T22:44:43.000Z
\n", + "
" + ], + "text/plain": [ + " geometry datetime \\\n", + "0 POLYGON ((-90.92339 -28.63784, -88.13659 -25.8... 2019-04-20T09:42:53Z \n", + "1 POLYGON ((-72.56963 -0.28696, -70.40899 -3.350... 2019-05-17T11:26:30Z \n", + "2 POLYGON ((-73.19654 -0.02675, -71.0381 -3.0880... 2019-05-24T08:44:16Z \n", + "3 POLYGON ((-90.70751 -29.22035, -87.8886 -26.44... 2019-06-12T12:34:08Z \n", + "4 POLYGON ((-72.85289 -0.06564, -70.69566 -3.124... 2019-06-18T22:34:32Z \n", + "\n", + " storage:schemes \\\n", + "0 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "1 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "2 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "3 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "4 {'aws': {'type': 'aws-s3', 'platform': 'https:... \n", + "\n", + " start_datetime end_datetime \n", + "0 2019-04-20T09:42:53.000Z 2019-04-20T09:52:33.000Z \n", + "1 2019-05-17T11:26:30.000Z 2019-05-17T11:36:36.000Z \n", + "2 2019-05-24T08:44:16.000Z 2019-05-24T08:54:31.000Z \n", + "3 2019-06-12T12:34:08.000Z 2019-06-12T12:44:00.000Z \n", + "4 2019-06-18T22:34:32.000Z 2019-06-18T22:44:43.000Z " + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gedi_gdf = stac_search_to_gdf(\n", + " catalog_url=GEDI_STAC_URL,\n", + " collections=[GEDI_COLLECTION],\n", + " bbox=BBOX_BUF, # use buffered bbox for GEDI discovery\n", + " datetime=GEDI_DT,\n", + " limit=500,\n", + ")\n", + "print(f\"GEDI items found for {GEDI_COLLECTION}: {len(gedi_gdf)}\")\n", + "gedi_gdf.head()\n" + ] + }, + { + "cell_type": "markdown", + "id": "ab01e52c-d8e2-4fd6-b89e-32002c6b81f3", + "metadata": {}, + "source": [ + "## Map: AOI + NISAR + BIOMASS + GEDI\n", + "Interactive map showing all three datasets as different colored layers." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "16646ba5-6849-44eb-8d82-2c0e9fdfe774", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# One map with AOI + NISAR + BIOMASS + GEDI (different colors)\n", + "\n", + "m = folium.Map(location=[(miny + maxy) / 2, (minx + maxx) / 2], zoom_start=8, tiles=\"OpenStreetMap\")\n", + "\n", + "def _style(color, weight=2, fill_opacity=0.05):\n", + " return lambda _: {\"color\": color, \"weight\": weight, \"fillOpacity\": fill_opacity}\n", + "\n", + "# AOI outline (red)\n", + "folium.GeoJson(\n", + " data={\"type\": \"Feature\", \"geometry\": mapping(aoi_geom), \"properties\": {\"name\": \"AOI\"}},\n", + " name=\"AOI\",\n", + " style_function=_style(\"red\", weight=3, fill_opacity=0.0),\n", + ").add_to(m)\n", + "\n", + "# NISAR footprints (blue)\n", + "if len(nisar_gdf) > 0:\n", + " folium.GeoJson(\n", + " nisar_gdf,\n", + " name=\"NISAR\",\n", + " style_function=_style(\"blue\", weight=2, fill_opacity=0.05),\n", + " ).add_to(m)\n", + "\n", + "# BIOMASS footprints (green)\n", + "if len(biomass_gdf) > 0:\n", + " folium.GeoJson(\n", + " biomass_gdf,\n", + " name=\"BIOMASS\",\n", + " style_function=_style(\"green\", weight=2, fill_opacity=0.05),\n", + " ).add_to(m)\n", + "\n", + "# GEDI footprints (orange)\n", + "if len(gedi_gdf) > 0:\n", + " folium.GeoJson(\n", + " gedi_gdf,\n", + " name=\"GEDI L4A AGBD\",\n", + " style_function=_style(\"orange\", weight=1, fill_opacity=0.001),\n", + " ).add_to(m)\n", + "\n", + "folium.LayerControl(collapsed=False).add_to(m)\n", + "m" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}