# Load libraries
#!pip install -q earthaccess pandas xarray fsspec requests pystac_client
import datetime
import glob
import os
import earthaccess
import pandas as pd
import plotutils as putils
import requests
import xarray as xr
from earthaccess import Store
from pystac_client import Client
NASA Data Fusion Analysis of Derechos and Their Impact on Rural America
Run This Notebook
π Launch in VEDA JupyterHub (requires access)
To obtain credentials to VEDA Hub, follow this link for more information.
If you do not have a VEDA Jupyterhub Account you can launch this notebook on your local environment using MyBinder by clicking the icon below.
Environment Setup
# For retrieving data already catalogued in VEDA STAC
= "https://openveda.cloud/api/stac"
STAC_API_URL = "https://openveda.cloud/api/raster" RASTER_API_URL
What is a Derecho?
A derecho is a long-lasting, fast-moving windstorm that is produced from a line of severe thunderstorms. For a storm to be called a derecho, there must be:
- A concentrated area of severe wind reports over 400 miles (650β―km) in length and at least 60 miles (96β―km) wide.
- Several wind gusts reported over 75β―mph (120β―km/h).
- Sustained winds of at least 58β―mph (93β―km/h). (SPC)
Unlike single thunderstorms, derechos form within mesoscale (i.e., mid-sized) convective systems (MCS)βlarge storm clusters that produce strong, long-lasting straight-line winds.
Conditions that Help a Derecho Form Include:
- Strong instability (Convective Available Potential Energy (CAPE) over 2000β4000β―J/kg): provides energy for strong updrafts and intense thunderstorms.
- High low-level moisture (dewpoints of 65β75β―Β°F): keeps storms going by supplying moisture.
- Strong mid- and upper-level winds (wind shear over 40β―knots): help organize storms and push them forward.
- A well-defined cold pool: rain-cooled air at the surface strengthens the storm by increasing wind speeds at the front of the system.
Example: Soil Moisture from GLDAS
Retrieve Global Land Data Assimilation System (GLDAS) data from the NASA EarthData portal. GLDAS data helps assess soil moisture levels before and after the storm, showing how pre-existing drought conditions contributed to dust transport and how heavy rainfall may have impacted runoff and flooding.
Processing steps:
1.) Provide credentials for EarthAccess authentication
2.) Select a start and end date for the data granules
3.) Add model name and version from EarthData portal
4.) Add the prefix for the data within the bucket (e.g., remote sensing mission, reanalysis model, etc.)
5.) Retrieve all files within the collection based on the start and end date. (If the same year is selected for start_date and end_date, then only the common year will be retrieved. Else all granules are retrived.
6.) Filter all collected granules based on the start_ and end_date range.
7.) Compute daily mean of hourly files
8.) Plot variable based on coordinates selected
9.) Create a .gif over the start_ and end_date range
# ββ Authenticate ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= earthaccess.login()
auth
= Store(auth) store
Select dates and find links
# ββ Search by date ββββββββ(requires >2GB RAM if more than 40 dates are selected)βββββββββββββββ
= datetime.datetime(2022, 4, 1)
start_date = datetime.datetime(2022, 5, 12)
end_date = pd.date_range(start=start_date, end=end_date, freq="D").to_pydatetime()
date_array
# ββ Dataset βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= "GLDAS_NOAH025_3H"
short_name = "2.1"
version = "SoilMoi0_10cm_inst" # Only select a single variable of interest
variable
# get all granules
print("Retrieving data granules from Earthaccess")
= earthaccess.search_data(
results =short_name,
short_name=version,
version=(start_date, end_date),
temporal=True,
cloud_hosted
)
# grab the S3 URLs
= [g["umm"]["RelatedUrls"][1]["URL"] for g in results]
urls print(f"Found {len(urls)} files")
# ββ Open granules βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= earthaccess.open(results)
granules = earthaccess.get_s3_filesystem(results=results) # autoβpicks the right DAAC & creds
fs
= {"cache_type": "mmap"}
fsspec_caching = slice(24, 50)
lat_range = slice(-125, -66)
lon_range
def subset(ds):
return ds[[variable]].sel(lat=lat_range, lon=lon_range)
= xr.open_mfdataset(
ds open(url, **fsspec_caching) for url in urls],
[fs.="auto",
chunks="time",
concat_dim="nested",
combine=True,
parallel="minimal",
data_vars="minimal",
coords="override",
compat="exact",
join=subset,
preprocess
)
# ββ Compute Daily Mean βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= ds.resample(time="1D").mean(dim="time").compute()
ds_resampled ds_resampled
Retrieving data granules from Earthaccess
Found 329 files
<xarray.Dataset> Size: 4MB Dimensions: (time: 42, lat: 104, lon: 236) Coordinates: * lat (lat) float32 416B 24.12 24.38 24.62 ... 49.62 49.88 * lon (lon) float32 944B -124.9 -124.6 ... -66.38 -66.12 * time (time) datetime64[ns] 336B 2022-04-01 ... 2022-05-12 Data variables: SoilMoi0_10cm_inst (time, lat, lon) float32 4MB nan nan nan ... nan nan nan Attributes: (12/16) missing_value: -9999.0 tavg definition:: past 3-hour average acc definition:: past 3-hour accumulation inst definition:: instantaneous title: GLDAS2.1 LIS land surface model output institution: NASA GSFC ... ... comment: website: https://ldas.gsfc.nasa.gov/gldas, https:... MAP_PROJECTION: EQUIDISTANT CYLINDRICAL SOUTH_WEST_CORNER_LAT: -59.875 SOUTH_WEST_CORNER_LON: -179.875 DX: 0.25 DY: 0.25
Create interactive map
# Use the plot_folium_from_xarray function from plotutils
putils.plot_folium_from_xarray(=ds_resampled["SoilMoi0_10cm_inst"],
dataset="2022-05-11",
day_select=[-130, 33, -90, 50],
bbox="Soil Moisture from GLDAS (mΒ³/mΒ³) [subset]",
var_name_for_title="YlOrRd_r",
matplot_ramp=4.5,
zoom_level=False,
flipud=False,
save_tif=None,
tif_filename="4326",
crs=0.8,
opacity )
Create an animation over dates
# Usage:
putils.matplotlib_gif(=ds_resampled["SoilMoi0_10cm_inst"],
data=[-130, 33, -90, 50],
bbox="soil_matplotlib.gif",
gif_savename=2,
duration="YlOrRd_r",
cmap )
<IPython.core.display.Image object>
β
Saved GIF β soil_matplotlib.gif
Example: Soil moisture data from WLDAS
This example pulls soil moisture data from the Western Land Data Assimilation System (WLDAS) via the VEDA STAC catalog and visualize.The WLDAS is a regional instance of NASAβs Land Information System (LIS), developed at Goddard Space Flight Center for the western United States. It integrates meteorological forcings (precipitation, radiation, temperature, humidity, wind, surface pressure) and satellite-derived parameters (vegetation class, soil texture, elevation) into the Noah-MP land surface model using data assimilation techniques.
Soil moisture critically controls the partitioning of net surface energy into latent (evapotranspiration) versus sensible (heating) fluxes. Wetter soils favor latent heat, stabilizing the boundary layer, whereas drier soils boost sensible heating, enhancing near-surface temperature and convective available potential energy (CAPE). These processes govern where and when thunderstorms can initiate and organize.
Processing steps:
1.) Choose STAC catalog ID and date
2.) Retrieve collection information and items from VEDA STAC catalog
3.) Retrieve item statistics and tiling information
4.) Plot data
Choose variable and retrieve json from VEDA STAC catalogue
# TODO: Change collection_ID and date
= Client.open(STAC_API_URL)
client_STAC
= "wldas-derecho-sm"
collection_id = "2022-05-11"
date
= client_STAC.search(collections=[collection_id], datetime=date)
results
# ββ VEDA Collection Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= list(results.items())
items assert len(items) != 0, "No items found"
= items[0]
item = item.get_collection()
collection
# grab the dashboard render block
= collection.extra_fields["renders"]["dashboard"]
dashboard_render
= dashboard_render["assets"][0]
assets = dashboard_render["rescale"]
((vmin, vmax),)
collection
- type "Collection"
- id "wldas-derecho-sm"
- stac_version "1.0.0"
- description "WLDAS data for the Western United States on May 11th, 2022."
links[] 5 items
0
- rel "items"
- href "https://openveda.cloud/api/stac/collections/wldas-derecho-sm/items"
- type "application/geo+json"
1
- rel "parent"
- href "https://openveda.cloud/api/stac/"
- type "application/json"
2
- rel "root"
- href "https://openveda.cloud/api/stac"
- type "application/json"
- title "VEDA (Visualization, Exploration, and Data Analysis) STAC API"
3
- rel "http://www.opengis.net/def/rel/ogc/1.0/queryables"
- href "https://openveda.cloud/api/stac/collections/wldas-derecho-sm/queryables"
- type "application/schema+json"
- title "Queryables"
4
- rel "self"
- href "https://openveda.cloud/api/stac/collections/wldas-derecho-sm"
- type "application/json"
stac_extensions[] 2 items
- 0 "https://stac-extensions.github.io/render/v1.0.0/schema.json"
- 1 "https://stac-extensions.github.io/item-assets/v1.0.0/schema.json"
renders
dashboard
bidx[] 1 items
- 0 1
assets[] 1 items
- 0 "cog_default"
rescale[] 1 items
0[] 2 items
- 0 0
- 1 0.4
- resampling "nearest"
- colormap_name "rdylgn"
item_assets
cog_default
- type "image/tiff; application=geotiff; profile=cloud-optimized"
roles[] 2 items
- 0 "data"
- 1 "layer"
- title "Default COG Layer"
- description "Cloud optimized default layer to display on map"
- datetime_range "day"
- dashboard:is_periodic False
- dashboard:time_density "day"
- title "WLDAS Soil Moisture Content (0-10cm)"
extent
spatial
bbox[] 1 items
0[] 4 items
- 0 -179.1473680657398
- 1 17.67439908061759
- 2 179.7784301170628
- 3 71.38922567703183
temporal
interval[] 1 items
0[] 2 items
- 0 "2022-05-11T00:00:00Z"
- 1 "2022-05-11T23:59:59Z"
- license "CC0-1.0"
providers[] 1 items
0
- name "NASA VEDA"
roles[] 1 items
- 0 "host"
- url "https://www.earthdata.nasa.gov/dashboard/"
summaries
datetime[] 1 items
- 0 "2022-05-11T00:00:00Z"
assets
thumbnail
- href "https://thumbnails.openveda.cloud/veda_derecho_thumbnail.png"
- type "image/png"
- title "Thumbnail"
- description "Photo by Jim Reed Photography (Intense derecho thunderstorm as it sweeps across farmland on September 23, 2018) "
roles[] 1 items
- 0 "thumbnail"
Retrieve tiling information
# ββ VEDA Tile Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= "hot"
colormap_name
# Build endpoint URL without worrying about trailing slashes
= requests.get(
response f"{RASTER_API_URL.rstrip('/')}/collections/{collection_id}"
f"/items/{item.id}/WebMercatorQuad/tilejson.json?"
f"&assets={assets}"
f"&color_formula=gamma+r+1.05&colormap_name={colormap_name}"
f"&rescale={vmin},{vmax}",
)
response.raise_for_status()
= response.json()
tiles print(tiles)
{'tilejson': '2.2.0', 'version': '1.0.0', 'scheme': 'xyz', 'tiles': ['https://openveda.cloud/api/raster/collections/wldas-derecho-sm/items/WLDAScog_SM_2022-05-11/tiles/WebMercatorQuad/{z}/{x}/{y}@1x?assets=cog_default&color_formula=gamma+r+1.05&colormap_name=hot&rescale=0%2C0.4'], 'minzoom': 0, 'maxzoom': 24, 'bounds': [-179.1473680657398, 17.67439908061759, 179.7784301170628, 71.38922567703183], 'center': [0.3155310256614996, 44.53181237882471, 0]}
Plot data
# Use the new plot_folium_from_VEDA_STAC function
= putils.plot_folium_from_VEDA_STAC(
m =tiles["tiles"][0],
tiles_url_template=[41.5, -110],
center_coords=5,
zoom_level=(vmin, vmax),
rescale=colormap_name,
colormap_name=False, # to better match VEDA colors and matplotlib colors
capitalize_cmap="WLDAS soil moisture",
layer_name=f"{date}T00:00:00Z",
date="Soil Moisture (m3/m3)",
colorbar_caption="VEDA WLDAS Soil Moisture",
attribution="WLDAS Soil Moisture Data",
tile_name=0.8,
opacity="800px",
height
)
# Display the map
m
Example: Hourly Aerosol Optical Thickness from MERRA-2
This example retrieves MERRA-2 hourly files for Aerosol Optical Thickness. Aerosol Optical Thickness (AOT), also called Aerosol Optical Depth (AOD), is a dimensionless measure of how much sunlight aerosolsβtiny particles like dust, smoke or sea saltβscatter and absorb as it travels through a column of atmosphere. In practical terms, an AOT of 0.1 means only 10 % of the direct solar beam is extinguished by aerosols before reaching the surface.
The intense straight-line winds in derechos can uplift large quantities of soil and dust, dramatically increasing AOT downwind. Tracking AOT in near-real-time reveals the spatial extent and intensity of these airborne dust plumes.
Processing steps:
1.) Select a start and end date for the data granules
2.) Add model name and version from EarthData portal
3.) Add the prefix for the data within the bucket (e.g., remote sensing mission, reanalysis model, etc.)
4.) Retrive all files within the collection based on the start and end date. (If the same year is selected for start_date and end_date, then only the common year will be retrieved. Else all granules are retrived.
5.) Filter all collected granules based on the start_ and end_date range.
6.) Plot variable based on coordinates selected
7.) Create a .gif over the start_ and end_date range
Select and filter
# ββ Search by date ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= datetime.datetime(2022, 5, 12)
start_date = datetime.datetime(2022, 5, 12)
end_date = pd.date_range(start=start_date, end=end_date, freq="D").to_pydatetime()
date_array
# ββ Dataset βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= "M2T1NXAER"
short_name = "5.12.4"
version = "TOTEXTTAU" # Total aerosol extinction optical thickness
variable
# get all granules
print("Retrieving data granules from Earthaccess")
= earthaccess.search_data(
results =short_name,
short_name=version,
version=(start_date, end_date),
temporal=True,
cloud_hosted
)
# grab the S3 URLs
= [g["umm"]["RelatedUrls"][1]["URL"] for g in results]
urls print(f"Found {len(urls)} files")
# ββ Open granules βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= earthaccess.open(results)
granules = earthaccess.get_s3_filesystem(results=results) # autoβpicks the right DAAC & creds
fs
= {"cache_type": "mmap"}
fsspec_caching = slice(24, 50)
lat_range = slice(-125, -66)
lon_range
def subset(ds):
return ds[[variable]].sel(lat=lat_range, lon=lon_range)
= xr.open_mfdataset(
ds open(url, **fsspec_caching) for url in urls],
[fs.="auto",
chunks="time",
concat_dim="nested",
combine=True,
parallel="minimal",
data_vars="minimal",
coords="override",
compat="exact",
join=subset,
preprocess
)
ds
Retrieving data granules from Earthaccess
Found 1 files
<xarray.Dataset> Size: 485kB Dimensions: (time: 24, lat: 53, lon: 95) Coordinates: * lon (lon) float64 760B -125.0 -124.4 -123.8 ... -67.5 -66.88 -66.25 * lat (lat) float64 424B 24.0 24.5 25.0 25.5 ... 48.5 49.0 49.5 50.0 * time (time) datetime64[ns] 192B 2022-05-12T00:30:00 ... 2022-05-12T... Data variables: TOTEXTTAU (time, lat, lon) float32 483kB dask.array<chunksize=(13, 53, 95), meta=np.ndarray> Attributes: (12/30) History: Original file generated: Sun May 22 22... Comment: GMAO filename: d5124_m2_jan10.tavg1_2d... Filename: MERRA2_400.tavg1_2d_aer_Nx.20220512.nc4 Conventions: CF-1 Institution: NASA Global Modeling and Assimilation ... References: http://gmao.gsfc.nasa.gov ... ... Contact: http://gmao.gsfc.nasa.gov identifier_product_doi: 10.5067/KLICLTZ8EM9D RangeBeginningDate: 2022-05-12 RangeBeginningTime: 00:00:00.000000 RangeEndingDate: 2022-05-12 RangeEndingTime: 23:59:59.000000
Plot time series of Aerosols
Open the MERRA file and plot by hour in a .gif for the selected variable AOT
# Use the matplotlib_gif function from plotutils
putils.matplotlib_gif(=ds["TOTEXTTAU"],
data=[-130, 33, -90, 50],
bbox="merra_aot.gif",
gif_savename=2,
duration="YlOrRd_r",
cmap; )
<IPython.core.display.Image object>
β
Saved GIF β merra_aot.gif
Example: Aerosol Optical Depth with MODIS
Pull MODIS Aerosol Optical Depth data from the VEDA STAC catalog and visualize
= "modis-derecho"
collection_id = "2022-05-12"
date
= client_STAC.search(collections=[collection_id], datetime=date)
results
# ββ VEDA Collection Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= list(results.items())
items assert len(items) != 0, "No items found"
= items[0]
item = item.get_collection()
collection
# grab the dashboard render block
= collection.extra_fields["renders"]["dashboard"]
dashboard_render
= dashboard_render["assets"][0]
assets = dashboard_render["rescale"]
((vmin, vmax),)
collection
- type "Collection"
- id "modis-derecho"
- stac_version "1.0.0"
- description "MODIS AOD over the Northern Plains region during the daytime on May 12, 2022"
links[] 5 items
0
- rel "items"
- href "https://openveda.cloud/api/stac/collections/modis-derecho/items"
- type "application/geo+json"
1
- rel "parent"
- href "https://openveda.cloud/api/stac/"
- type "application/json"
2
- rel "root"
- href "https://openveda.cloud/api/stac"
- type "application/json"
- title "VEDA (Visualization, Exploration, and Data Analysis) STAC API"
3
- rel "http://www.opengis.net/def/rel/ogc/1.0/queryables"
- href "https://openveda.cloud/api/stac/collections/modis-derecho/queryables"
- type "application/schema+json"
- title "Queryables"
4
- rel "self"
- href "https://openveda.cloud/api/stac/collections/modis-derecho"
- type "application/json"
stac_extensions[] 2 items
- 0 "https://stac-extensions.github.io/render/v1.0.0/schema.json"
- 1 "https://stac-extensions.github.io/item-assets/v1.0.0/schema.json"
renders
dashboard
bidx[] 1 items
- 0 1
assets[] 1 items
- 0 "cog_default"
rescale[] 1 items
0[] 2 items
- 0 0
- 1 0.2
- colormap_name "ylorbr"
item_assets
cog_default
- type "image/tiff; application=geotiff; profile=cloud-optimized"
roles[] 2 items
- 0 "data"
- 1 "layer"
- title "Default COG Layer"
- description "Cloud optimized default layer to display on map"
- dashboard:is_periodic False
- dashboard:time_density "day"
- title "MODIS Aersol Optical Depth (AOD) for May 12, 2022"
extent
spatial
bbox[] 1 items
0[] 4 items
- 0 -104.9587947491025
- 1 39.60418504240213
- 2 -87.8641172323396
- 3 49.635984790222665
temporal
interval[] 1 items
0[] 2 items
- 0 "2022-05-12T00:00:00Z"
- 1 "2022-05-12T00:00:00Z"
- license "CC0-1.0"
providers[] 1 items
0
- name "NASA VEDA"
roles[] 1 items
- 0 "host"
- url "https://www.earthdata.nasa.gov/dashboard/"
summaries
datetime[] 1 items
- 0 "2022-05-12T00:00:00Z"
assets
thumbnail
- href "https://thumbnails.openveda.cloud/veda_derecho_thumbnail.png"
- type "image/png"
- title "Thumbnail"
- description "Photo by Jim Reed Photography (Intense derecho thunderstorm as it sweeps across farmland on September 23, 2018)"
roles[] 1 items
- 0 "thumbnail"
# ββ VEDA Tile Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= "viridis"
colormap_name
# Build endpoint URL without worrying about trailing slashes
= requests.get(
response f"{RASTER_API_URL.rstrip('/')}/collections/{collection_id}"
f"/items/{item.id}/WebMercatorQuad/tilejson.json?"
f"&assets={assets}"
f"&color_formula=gamma+r+1.05&colormap_name={colormap_name}"
f"&rescale={vmin},{vmax}",
)
response.raise_for_status()
= response.json()
tiles print(tiles)
{'tilejson': '2.2.0', 'version': '1.0.0', 'scheme': 'xyz', 'tiles': ['https://openveda.cloud/api/raster/collections/modis-derecho/items/derecho_MODIS_AOD_2022-05-12/tiles/WebMercatorQuad/{z}/{x}/{y}@1x?assets=cog_default&color_formula=gamma+r+1.05&colormap_name=viridis&rescale=0%2C0.2'], 'minzoom': 0, 'maxzoom': 24, 'bounds': [-104.9587947491025, 39.60418504240213, -87.8641172323396, 49.635984790222665], 'center': [-96.41145599072104, 44.62008491631239, 0]}
# Use the new plot_folium_from_VEDA_STAC function
= putils.plot_folium_from_VEDA_STAC(
m =tiles["tiles"][0],
tiles_url_template=[42.5, -96],
center_coords=7,
zoom_level=(vmin, vmax),
rescale=colormap_name,
colormap_name="MODIS AOD",
layer_name=f"{date}T00:00:00Z",
date="Aerosol Optical Depth",
colorbar_caption="VEDA MODIS AOD",
attribution="MODIS AOD",
tile_name=0.8,
opacity="800px",
height
)
# Display the map
m
Example: Wind Gusts
This examples pulls data the National Centers for Environmental Informationβs (NCEI) Interpolated Wind Gusts data from the VEDA STAC catalog and visualizes. The NCEI Interpolated Wind Gusts product takes the discrete stationβreported peak wind gusts from the NCEI Storm Events Databaseβa standardized archive of severeβweather observations dating back to 1950βand uses spatial interpolation to generate a continuous gridded field of maximum gust speeds across the derecho swath.
By filling in the gaps between point measurements, it reveals the full geographic extent and intensity gradients of the derechoβs outflow winds, often uncovering zones of extreme gust (e.g., 70 mph +) that lie between and beyond individual station sites.
= "windgusts-derecho"
collection_id = "2022-05-12"
date
= client_STAC.search(collections=[collection_id], datetime=date)
results
# ββ VEDA Collection Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= list(results.items())
items assert len(items) != 0, "No items found"
= items[0]
item = item.get_collection()
collection
# grab the dashboard render block
= collection.extra_fields["renders"]["dashboard"]
dashboard_render
= dashboard_render["assets"][0]
assets = dashboard_render["rescale"]
((vmin, vmax),)
collection
- type "Collection"
- id "windgusts-derecho"
- stac_version "1.0.0"
- description "NCEI Storm Events Database wind gusts exceeding 70mph for the derecho of May 12th, 2022"
links[] 5 items
0
- rel "items"
- href "https://openveda.cloud/api/stac/collections/windgusts-derecho/items"
- type "application/geo+json"
1
- rel "parent"
- href "https://openveda.cloud/api/stac/"
- type "application/json"
2
- rel "root"
- href "https://openveda.cloud/api/stac"
- type "application/json"
- title "VEDA (Visualization, Exploration, and Data Analysis) STAC API"
3
- rel "http://www.opengis.net/def/rel/ogc/1.0/queryables"
- href "https://openveda.cloud/api/stac/collections/windgusts-derecho/queryables"
- type "application/schema+json"
- title "Queryables"
4
- rel "self"
- href "https://openveda.cloud/api/stac/collections/windgusts-derecho"
- type "application/json"
stac_extensions[] 2 items
- 0 "https://stac-extensions.github.io/render/v1.0.0/schema.json"
- 1 "https://stac-extensions.github.io/item-assets/v1.0.0/schema.json"
renders
dashboard
bidx[] 1 items
- 0 1
assets[] 1 items
- 0 "cog_default"
rescale[] 1 items
0[] 2 items
- 0 75
- 1 100
- resampling "nearest"
- colormap_name "bupu"
item_assets
cog_default
- type "image/tiff; application=geotiff; profile=cloud-optimized"
roles[] 2 items
- 0 "data"
- 1 "layer"
- title "Default COG Layer"
- description "Cloud optimized default layer to display on map"
- dashboard:is_periodic False
- dashboard:time_density "day"
- title "NCEI Wind Gusts for 05/12/2022"
extent
spatial
bbox[] 1 items
0[] 4 items
- 0 -104.98043829543191
- 1 39.61453189361588
- 2 -87.85370728055949
- 3 49.62204006079752
temporal
interval[] 1 items
0[] 2 items
- 0 "2022-05-12T00:00:00Z"
- 1 "2022-05-12T00:00:00Z"
- license "CC0-1.0"
providers[] 1 items
0
- name "NASA VEDA"
roles[] 1 items
- 0 "host"
- url "https://www.earthdata.nasa.gov/dashboard/"
summaries
datetime[] 1 items
- 0 "2022-05-12T00:00:00Z"
assets
thumbnail
- href "https://thumbnails.openveda.cloud/veda_derecho_thumbnail.png"
- type "image/png"
- title "Thumbnail"
- description "Photo by Jim Reed Photography (Intense derecho thunderstorm as it sweeps across farmland on September 23, 2018)"
roles[] 1 items
- 0 "thumbnail"
# ββ VEDA Tile Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= "viridis"
colormap_name
# Build endpoint URL without worrying about trailing slashes
= requests.get(
response f"{RASTER_API_URL.rstrip('/')}/collections/{collection_id}"
f"/items/{item.id}/WebMercatorQuad/tilejson.json?"
f"&assets={assets}"
f"&color_formula=gamma+r+1.05&colormap_name={colormap_name}"
f"&rescale={vmin},{vmax}",
)
response.raise_for_status()
= response.json()
tiles print(tiles)
{'tilejson': '2.2.0', 'version': '1.0.0', 'scheme': 'xyz', 'tiles': ['https://openveda.cloud/api/raster/collections/windgusts-derecho/items/Windgusts_cog_2022-05-12/tiles/WebMercatorQuad/{z}/{x}/{y}@1x?assets=cog_default&color_formula=gamma+r+1.05&colormap_name=viridis&rescale=75%2C100'], 'minzoom': 0, 'maxzoom': 24, 'bounds': [-104.98043829543191, 39.61453189361588, -87.85370728055949, 49.62204006079752], 'center': [-96.41707278799569, 44.618285977206696, 0]}
# Use the new plot_folium_from_VEDA_STAC function
= putils.plot_folium_from_VEDA_STAC(
m =tiles["tiles"][0],
tiles_url_template=[45, -97.7],
center_coords=6,
zoom_level=(vmin, vmax),
rescale=colormap_name,
colormap_name=False, # to better match VEDA colors and matplotlib colors
capitalize_cmap="Wind Gusts",
layer_name=f"{date}T00:00:00Z",
date="Wind Gusts (mph)",
colorbar_caption="VEDA Wind Gusts",
attribution="Wind Gusts",
tile_name=0.8,
opacity="800px",
height
)
# Display the map
m
Example: Black Marble Night Lights
This examples pulls the NASA Black Marble Night Lights data from the VEDA STAC catalog and visualizes. During extreme windstorms such as derechos, sudden drops in nighttime brightness in the Black Marble imagery reveal where power infrastructure has failed and outages have occurred, while the re-illumination of areas over subsequent days tracks the pace and extent of electrical service restoration. This makes Black Marble a powerful, near-real-time proxy for assessing societal impacts and grid resilience in the stormβs wake.
= "nightlights-derecho"
collection_id = "2022-05-10"
date
= client_STAC.search(collections=[collection_id], datetime=date)
results
# ββ VEDA Collection Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= list(results.items())
items assert len(items) != 0, "No items found"
= items[0]
item = item.get_collection()
collection
# grab the dashboard render block
= collection.extra_fields["renders"]["dashboard"]
dashboard_render
= dashboard_render["assets"][0]
assets = dashboard_render["rescale"]
((vmin, vmax),)
collection
- type "Collection"
- id "nightlights-derecho"
- stac_version "1.0.0"
- description "Difference in nightlights for the North Plains from 5/10/2022 and 5/16/2022 to demonstrate power outages from the derecho"
links[] 5 items
0
- rel "items"
- href "https://openveda.cloud/api/stac/collections/nightlights-derecho/items"
- type "application/geo+json"
1
- rel "parent"
- href "https://openveda.cloud/api/stac/"
- type "application/json"
2
- rel "root"
- href "https://openveda.cloud/api/stac"
- type "application/json"
- title "VEDA (Visualization, Exploration, and Data Analysis) STAC API"
3
- rel "http://www.opengis.net/def/rel/ogc/1.0/queryables"
- href "https://openveda.cloud/api/stac/collections/nightlights-derecho/queryables"
- type "application/schema+json"
- title "Queryables"
4
- rel "self"
- href "https://openveda.cloud/api/stac/collections/nightlights-derecho"
- type "application/json"
stac_extensions[] 2 items
- 0 "https://stac-extensions.github.io/render/v1.0.0/schema.json"
- 1 "https://stac-extensions.github.io/item-assets/v1.0.0/schema.json"
renders
dashboard
bidx[] 1 items
- 0 1
assets[] 1 items
- 0 "cog_default"
rescale[] 1 items
0[] 2 items
- 0 -255
- 1 255
- resampling "nearest"
- colormap_name "bwr"
item_assets
cog_default
- type "image/tiff; application=geotiff; profile=cloud-optimized"
roles[] 2 items
- 0 "data"
- 1 "layer"
- title "Default COG Layer"
- description "Cloud optimized default layer to display on map"
- dashboard:is_periodic False
- dashboard:time_density "day"
- title "VIIRS Night Lights Derecho"
extent
spatial
bbox[] 1 items
0[] 4 items
- 0 -112.07926856247974
- 1 39.47957304015183
- 2 -88.2545230530161
- 3 50.52441131325872
temporal
interval[] 1 items
0[] 2 items
- 0 "2022-05-10T00:00:00Z"
- 1 "2022-05-10T00:00:00Z"
- license "CC0-1.0"
providers[] 1 items
0
- name "NASA VEDA"
roles[] 1 items
- 0 "host"
- url "https://www.earthdata.nasa.gov/dashboard/"
summaries
datetime[] 1 items
- 0 "2022-05-10T00:00:00Z"
assets
thumbnail
- href "https://thumbnails.openveda.cloud/veda_derecho_thumbnail.png"
- type "image/png"
- title "Thumbnail"
- description "Photo by Jim Reed Photography (Intense derecho thunderstorm as it sweeps across farmland on September 23, 2018)"
roles[] 1 items
- 0 "thumbnail"
# ββ VEDA Tile Request βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
= "bwr"
colormap_name
# Build endpoint URL without worrying about trailing slashes
= requests.get(
response f"{RASTER_API_URL.rstrip('/')}/collections/{collection_id}"
f"/items/{item.id}/WebMercatorQuad/tilejson.json?"
f"&assets={assets}"
f"&color_formula=gamma+r+1.05&colormap_name={colormap_name}"
f"&rescale={vmin},{vmax}",
)
response.raise_for_status()
= response.json()
tiles print(tiles)
{'tilejson': '2.2.0', 'version': '1.0.0', 'scheme': 'xyz', 'tiles': ['https://openveda.cloud/api/raster/collections/nightlights-derecho/items/Nightlightscog_2022-05-10/tiles/WebMercatorQuad/{z}/{x}/{y}@1x?assets=cog_default&color_formula=gamma+r+1.05&colormap_name=bwr&rescale=-255%2C255'], 'minzoom': 0, 'maxzoom': 24, 'bounds': [-112.07926856247974, 39.47957304015183, -88.2545230530161, 50.52441131325872], 'center': [-100.16689580774792, 45.00199217670527, 0]}
# Use the new plot_folium_from_VEDA_STAC function
= putils.plot_folium_from_VEDA_STAC(
m =tiles["tiles"][0],
tiles_url_template=[45, -93],
center_coords=8,
zoom_level=(vmin, vmax),
rescale=colormap_name,
colormap_name=False, # to better match VEDA colors and matplotlib colors
capitalize_cmap="Black Marble Night Lights",
layer_name=f"{date}T00:00:00Z",
date="Artificial Light",
colorbar_caption="VEDA Black Marble Night Lights",
attribution="Black Marble Night Lights",
tile_name=0.8,
opacity="800px",
height
)
print(
"Visualization of St. Paul, Minnesota where values approaching 255 indicate power outages."
)# Display the map
m
Visualization of St. Paul, Minnesota where values approaching 255 indicate power outages.
Example: Global Precipitation
Pull NASAβs Global Precipitation Measurement (GPM) data through the Common Metadata Repository (CMR) STAC API. NASAβs GPM uses satellites to measure Earthβs rain and snowfall for the benefit of mankind. Launched by NASA and JAXA on Feb. 27th, 2014, GPM is an international mission that sets the standard for spaceborne precipitation measurements.
# Specific for May 05, 2022 (using titiler-cmr request)
= "2022-05-12"
date = "https://staging.openveda.cloud/api/titiler-cmr/tiles/WebMercatorQuad/{z}/{x}/{y}@1x?"
basetile_URL = f"datetime={date}T00%3A00%3A00.000Z%2F{date}T23%3A59%3A59.999Z&resampling=bilinear&variable=precipitation&colormap_name=gnbu&rescale=0%2C46&concept_id=C2723754864-GES_DISC&backend=xarray"
tile_URL = f"{basetile_URL}{tile_URL}" tilejson_url
= putils.plot_folium_from_VEDA_STAC(
m =tilejson_url,
tiles_url_template="GPM Imerge Precipitation",
layer_name="mm/hr",
colorbar_caption="2022-05-12",
date="Blues",
colormap_name=False, # to better match VEDA colors and matplotlib colors
capitalize_cmap=[46.55, -96.94],
center_coords=5,
zoom_level="800px",
height=(0, 46),
rescale
)
m
Economic Impact
The economic impact reached beyond the crop fields. Many grain silos, irrigation systems, and farm buildings were also damaged or destroyed, adding to the financial burden on farmers. See image below to identify crop types across the Midwest and the Storm Prediction Center reports across the Midwest.
Compare Corn vs Soybean
Use the slider below to compare the USDA corn and soybean land cover for the year 2022 and all unfiltered storm reports collected by the Storm Prediction Center (SPC) on May 12, 2022.
Image credit USDA and Storm Prediction Center.
# Usage example:
= "images/derecho/Derecho-Crop.jpg"
img1_path = "images/derecho/Derecho-storm-reports.jpg"
img2_path
=800) putils.create_pausable_blend_slider(img1_path, img2_path, width
Clean Up (Optional)
Remove any .gif files that were created to save on storage space. Additionally, remove any core files that were created if the kernel crashed.
# find all .gif files in the current directory
for gif_path in glob.glob("*.gif"):
try:
os.remove(gif_path)print(f"Removed {gif_path}")
except OSError as e:
print(f"Error removing {gif_path}: {e}")
# find all core files in the current directory
for core_path in glob.glob("core.*"):
try:
os.remove(core_path)print(f"Removed {core_path}")
except OSError as e:
print(f"Error removing {core_path}: {e}")
Removed soil_matplotlib.gif
Removed merra_aot.gif
Removed core.469