Holoviews to HoloViews¶
Interacting between HoloViews objects.
Pros:
Dynamically generate values
All in Python
Cons:
Interactivity may not be retained when saved
May require backend server
References:
Tap for update plot¶
Server required.
[7]:
import xarray as xr
import holoviews as hv
hv.extension("bokeh")
ds = xr.tutorial.open_dataset("air_temperature").isel(time=slice(0, 3))
coord_stream = hv.streams.Tap(x=-88 + 360, y=40)
time_stream = hv.streams.Tap(x=ds["time"].values[0])
def create_geomap(x, y):
ds_sel = ds.sel(time=x, method="nearest")
return hv.Image(ds_sel, ["lon", "lat"], ["air"]).opts(
"Image", title=str(x)[:16], tools=["tap", "hover"])
def create_timeseries(x, y):
ds_sel = ds.sel(lon=x, lat=y, method="nearest")
return hv.Curve(ds_sel, ["time"], ["air"]).opts(
"Curve", title=f"{x:.1f}, {y:.1f}", framewise=True, tools=["tap", "hover"])
def create_point(x, y):
return hv.Points((x, y)).opts("Points", color="red", marker="x", size=25)
def create_vline(x, y):
return hv.VLine(x).opts("VLine", color="red")
# create base plots
geomap = hv.DynamicMap(create_geomap, streams=[time_stream])
timeseries = hv.DynamicMap(create_timeseries, streams=[coord_stream])
# link source
coord_stream.source = geomap
time_stream.source = timeseries
# create annotations
coord_point = hv.DynamicMap(create_point, streams=[coord_stream])
time_vline = hv.DynamicMap(create_vline, streams=[time_stream])
# overlay + layout
layout = geomap * coord_point + timeseries * time_vline
[3]:
import panel as pn
pn.extension()
pn.pane.GIF("tap_for_update_plot.gif")
[3]:
Pointer Y for cross section (Hovmueller)¶
[4]:
import xarray as xr
import holoviews as hv
hv.extension("bokeh")
ds = xr.tutorial.open_dataset("air_temperature").isel(time=slice(0, 5))
def create_xsection(y):
ds_sel = ds.sel(lat=y, method="nearest")
return hv.Image(ds_sel, ["lon", "time"], ["air"])
def create_hline(y):
return hv.HLine(y).opts("HLine", color="red")
geomap = hv.Image(ds.isel(time=0), ["lon", "lat"], ["air"]).opts(
"Image", tools=["hover"])
lat_stream = hv.streams.PointerY(y=40, source=geomap)
xsection = hv.DynamicMap(create_xsection, streams=[lat_stream])
# create annotations
lat_hline = hv.DynamicMap(create_hline, streams=[lat_stream])
# overlay + layout
layout = geomap * lat_hline + xsection
[5]:
import panel as pn
pn.extension()
pn.pane.GIF("pointer_y_for_cross_section.gif")
[5]:
Pointer X for violin distribution¶
[6]:
import xarray as xr
import holoviews as hv
hv.extension("bokeh")
ds = xr.tutorial.open_dataset("air_temperature").isel(time=slice(0, 10))
ds = ds.coarsen(lat=3, lon=3, boundary="trim").mean()
def create_violin(x):
ds_sel = ds.sel(lon=x, method="nearest").to_dataframe()
return hv.Violin(ds_sel, ["lat"], ["air"]).opts(invert_axes=True)
def create_vline(x):
return hv.VLine(x).opts("VLine", color="red")
geomap = hv.Image(ds.isel(time=0), ["lon", "lat"], ["air"]).opts(
"Image", tools=["hover"])
lon_stream = hv.streams.PointerX(x=40, source=geomap)
violin = hv.DynamicMap(create_violin, streams=[lon_stream])
# create annotations
lon_vline = hv.DynamicMap(create_vline, streams=[lon_stream])
# overlay + layout
layout = geomap * lon_vline + violin
[7]:
import panel as pn
pn.extension()
pn.pane.GIF("pointer_x_for_violin_distribution.gif")
[7]:
Bounds x for subset x-axis limits¶
Works with overlays.
[8]:
import holoviews as hv
hv.extension("bokeh")
x = [0, 1, 2]
y = [3, 4, 5]
source = hv.Curve((x, y)).opts(
"Curve", width=500, height=125, labelled=["y"], default_tools=["xbox_select"]
)
stream = hv.streams.BoundsX(source=source, boundsx=(0, 2))
target = (hv.Curve((x, y)) * hv.Scatter((x, y)))
opts = dict(
axiswise=True,
framewise=True,
width=500,
height=250,
default_tools=["xwheel_zoom"],
active_tools=["xwheel_zoom"]
)
target = target.opts({"Curve": opts, "Scatter": opts, "Overlay": opts})
target = target.apply.opts(xlim=stream.param.boundsx)
layout = (source + target).opts(merge_tools=False).cols(1)
[9]:
import panel as pn
pn.extension()
pn.pane.GIF("bounds_x_for_subset_x_axis_limits.gif")
[9]: