Creating an Interactive Dashboard using hvPlot
and Panel
import xarray as xr
import holoviews as hv
import panel as pn
import hvplot.xarray
from holoviews import opts
pn.extension()
Data
In this notebook, we are going to load annual mean dataset of 2-m temperature from the ERA5 reanalysis that we preprocessed in Zarr format. Please see the preprocessing notebooks for the required steps.
rda_url = "https://data.rda.ucar.edu/"
annual_means = rda_url + "pythia_era5_24/annual_means/"
xrds = xr.open_dataset(annual_means + "temp_2m_annual_1940_2023.zarr", engine="zarr")
xrds
<xarray.Dataset> Size: 349MB Dimensions: (time: 84, latitude: 721, longitude: 1440) Coordinates: * latitude (latitude) float64 6kB 90.0 89.75 89.5 ... -89.5 -89.75 -90.0 * longitude (longitude) float64 12kB 0.0 0.25 0.5 0.75 ... 359.2 359.5 359.8 * time (time) datetime64[ns] 672B 1940-12-31 1941-12-31 ... 2023-12-31 Data variables: VAR_2T (time, latitude, longitude) float32 349MB ...
# Select the time range of interest
xrds = xrds.sel(time=slice('2017-01-01', '2023-12-31'))
xrds.load();
Panel Widgets
Panel provides a variety of widgets that can be used to build interactive dashboards. In this notebook, we are going to use some of these widgets. For the complete list of widgets, please see the Panel documentation.
The panel widgets that we are using are:
pn.widgets.Select
for selecting the variablepn.widgets.DatePicker
for selecting the datepn.widgets.Player
for making time series animations
w_var = pn.widgets.Select(name="Data Variable", options=list(xrds.data_vars))
dataset_controls = pn.WidgetBox(
"## Dataset Controls",
w_var,
)
dataset_controls
Now, let’s create dropdown widgets for selecting the colormap and plot type.
w_cmap = pn.widgets.Select(name="Colormap", options=["inferno", "plasma", "coolwarm"])
w_plot_type = pn.widgets.Select(
name="Plot Type", options=["Color Plot", "Contour"]
)
plot_controls = pn.WidgetBox(
"## Plot Controls",
w_plot_type,
w_cmap,
)
plot_controls
Now, let’s put together all the controls and the plot in a panel layout using pn.Row
and pn.Column
:
controls = pn.Column(dataset_controls, plot_controls)
controls
w_player = pn.widgets.Player(
value=0,
start=0,
end=len(xrds.time) - 1,
name="Year",
loop_policy="loop",
interval=300,
align="center",
width_policy="fit",
)
w_player
Plotting Function
def plot_ds(time, var, cmap, plot_type):
clim = (xrds[var].values.min(), xrds[var].values.max())
if plot_type == "Color Plot":
return (
xrds[var]
.isel(time=time)
.hvplot(
cmap=cmap,
title=str(f"{var} year {time}"),
clim=clim,
dynamic=False,
rasterize=True,
precompute=True,
)
.opts(framewise=False)
)
elif plot_type == "Contour":
return (
xrds[var]
.isel(time=time)
.hvplot.contour(
cmap=cmap,
dynamic=False,
rasterize=True,
title=str(f"{var} Year: {time}"),
clim=clim,
precompute=True,
)
.opts(framewise=False)
)
app = pn.Row(
controls,
pn.Column(
pn.panel(
hv.DynamicMap(
pn.bind(
plot_ds,
time=w_player,
var=w_var,
cmap=w_cmap,
plot_type=w_plot_type,
)
)
),
w_player,
),
).servable()
app