Panel to HoloViews (Javascript)¶
Interacting between Panel widgets and HoloViews objects using Javascript.
Pros:
No server necessary
Interactivity retained after saving to HTML
Cons:
File size may become large
References:
https://panel.holoviz.org/user_guide/Links.html#defining-javascript-callbacks
https://docs.bokeh.org/en/latest/docs/user_guide/styling.html
https://docs.bokeh.org/en/latest/docs/user_guide/annotations.html
Float slider for glyph fill alpha¶
This same concept can be applied for any styling including, but not limited to, size, fill_color, fill_alpha, line_width, etc.
[1]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
widget = pn.widgets.FloatSlider(value=1, step=0.01)
plot = hv.Points((x, y)).opts(size=10)
link = widget.jslink(plot, value='glyph.fill_alpha')
pn.Column(widget, plot)
[1]:
Text input for title text¶
[2]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
label = "Label"
widget = pn.widgets.TextInput(value=label)
plot = hv.Curve((x, y)).opts(title=label)
link = widget.jslink(plot, value="plot.title.text")
pn.Column(widget, plot)
[2]:
Text input for axis label text¶
This same concept can be applied for the y-axis.
[3]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
label = "Label"
widget = pn.widgets.TextInput(value=label)
plot = hv.Curve((x, y)).opts(xlabel=label)
link = widget.jslink(plot, value="xaxis.axis_label")
pn.Column(widget, plot)
[3]:
Float slider for label size¶
This same concept can be applied for both x and y axes.
[4]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
title = "Title"
widget = pn.widgets.FloatSlider(value=5, start=5, end=10)
plot = hv.Curve((x, y)).opts(title=title)
jscode = """
plot.title.text_font_size = String(source.value) + 'pt'
"""
link = widget.jslink(plot, code={'value': jscode})
pn.Column(widget, plot)
[4]:
Radio button group for label alignment¶
[5]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
title = "Title"
widget = pn.widgets.RadioButtonGroup(options=["left", "center", "right"])
plot = hv.Curve((x, y)).opts(title=title)
link = widget.jslink(plot, value="plot.title.align")
pn.Column(widget, plot)
[5]:
Range slider for axis limits¶
This same concept can be applied for the y-axis.
[6]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
widget = pn.widgets.RangeSlider(start=min(x), end=max(x))
plot = hv.Curve((x, y))
jscode = """
x_range.start = cb_obj.value[0];
x_range.end = cb_obj.value[1];
"""
link = widget.jslink(plot, code={'value': jscode})
pn.Column(widget, plot)
[6]:
Range slider for colorbar limits¶
[7]:
import panel as pn
import holoviews as hv
hv.extension('bokeh')
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
z = [[6, 7, 8], [9, 10, 11], [12, 13, 14]]
widget = pn.widgets.RangeSlider(start=min(min(z)), end=max(max(z)))
plot = hv.Image((x, y, z)).opts(colorbar=True)
jscode = """
color_mapper.low = cb_obj.value[0];
color_mapper.high = cb_obj.value[1];
"""
link = widget.jslink(plot, code={'value': jscode})
pn.Column(widget, plot)
[7]:
Float slider for data modification¶
[8]:
import holoviews as hv
import panel as pn
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [0, 0, 0]
widget = pn.widgets.FloatSlider(value=0, start=0, end=2, step=0.5)
plot = hv.Curve((x, y)).opts(ylim=(-1, 3))
jscode = """
var data = cds.data
var y = data['y']
for (var i = 0; i < y.length; i++) {
y[i] = cb_obj.value
}
cds.change.emit();
"""
link = widget.jslink(plot, code={'value': jscode})
pn.Column(widget, plot)
[8]:
Select for colorbar colors¶
Note, a greater number of cmaps is proportional to a larger file size!
[9]:
import panel as pn
import holoviews as hv
hv.extension("bokeh")
pn.extension()
x = [0, 1, 2]
y = [3, 4, 5]
z = [[6, 7, 8], [9, 10, 11], [12, 13, 14]]
cmaps = ["RdBu_r", "Reds"]
nums = [5, 11, 255]
# convert each named cmap to list of hexcodes for javascript to understand
cmaps_colors = {
f"{cmap}_n{num}": hv.plotting.util.process_cmap(cmap, num)
for cmap in cmaps for num in nums
}
widget = pn.widgets.Select(options=list(cmaps_colors))
plot = hv.Image((x, y, z)).opts(colorbar=True, cmap=cmaps_colors["RdBu_r_n5"])
jscode = """
color_mapper.palette = cmap_dict[source.value];
"""
link = widget.jslink(plot, code={"value": jscode}, args={"cmap_dict": cmaps_colors})
pn.Column(widget, plot)
[9]: