Skip to article frontmatterSkip to article content

NOAA GOES 19 Global Lightning Mapper case viewer

This notebook produces an interactive visualization of archived lightning strokes for a user-specified time range

import pandas as pd
import warnings
from datetime import datetime as dt, timezone, timedelta
import geopandas as gpd

import geoviews as gv
from geoviews import opts
from holoviews.element.tiles import OSM, EsriImagery

from lonboard import viz, Map, ScatterplotLayer

Specify the start date and time of the analysis window.

sd =  dt(2025, 10, 29, 0)
Limit the time range! 6 hours is good. Performance will decrease markedly with larger itme windows.
ed = sd + timedelta(hours=6)
sd
datetime.datetime(2025, 10, 29, 0, 0)
ed
datetime.datetime(2025, 10, 29, 6, 0)
timeString = sd.strftime("%Y%m%d")
timeString
'20251029'
warnings.simplefilter("ignore")
gv.extension('bokeh', 'matplotlib')
Loading...

Open the desired lightning dataset

file = f'/spare11/atm533/data/{timeString}_goes19_glm.parquet'
%time df = pd.read_parquet(file)
CPU times: user 51.1 ms, sys: 35.8 ms, total: 86.9 ms
Wall time: 43.4 ms

Apply a mask so that only those events in the requested time range are kept

mask = (df['time_start'] > sd) & (df['time_start'] <= ed) 
df = df.loc[mask]
df
Loading...

Assign the individual time of strokes to a time bin.

binInterval = '5min'
time_bins= pd.date_range(sd, ed, freq=binInterval)
df['TimeBin'] = df['time_start'].dt.round(binInterval)
df
Loading...

Create a GeoViews Dataset instance. We pass up to three arguments:

  1. The Pandas dataframe

  2. A list containing the kdims, aka key dimensions, the independent variables: time, lon and lat

  3. A list containing the vdims, aka variable dimensions, the dependent variables that vary according to the kdims. Choose the columns we are interested in plotting.

kdims = ['TimeBin','lon','lat']
vdims = ['flash_energy']

gv_ds = gv.Dataset(df,kdims) # no dependent variables, so no vdims

Now create GeoViews Points instances for the desired classes of lightning strokes.

Pass only the lon and lat dimensions as the first argument; the time dimension should become interactive.

Specify the width and height of the interactive plot. Adjust as necessary depending on what size display you are using.

plotWidth, plotHeight = 1200, 900
points = gv_ds.to(gv.Points, ['lon','lat'])
points.opts(color='red',size=8,marker='x',width=plotWidth, height=plotHeight, framewise=False);

Create and render the interactive plot.

Layer the desired classes of strokes over a background map.

layout = ( gv.tile_sources.OSM * points)
layout.opts(opts.Points(framewise=False,tools=['hover']))
layout
Loading...
Looks nice, but it will take increasingly long to render with greater time ranges (we told you that performance will scale inversely with the # of points!)

Let’s try another interactive, browser/GPU-based visualization tool ... Lonboard

Lonboard can very quickly read and render data from Geopandas dataframes (i.e., those that have a geo-relevant column, e.g. Points, Polygons, and/or MultiPolygons. Let’s read in and visualize the daily GLM file, which was already converted into Geopandas format.

glm_gdf = gpd.read_parquet(f'/spare11/atm533/data/{timeString}_goes19_glm_geo.parquet')
viz(glm_gdf)
Loading...
Zoom in between Jamaica and Cuba, and inspect the region near the center of Melissa As you can see, there is a tendency for points to cluster along latitude/longitude lines, creating a grid-like pattern. It is unclear as of yet whether this is emanating from the GLM's data stream itself, or is a by-product of the data processing that produced the Parquet file.