Bokeh#
Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).
import panel as pn
import numpy as np
import pandas as pd
pn.extension()
The Bokeh pane allows displaying any displayable Bokeh model inside a Panel app. Panel is itself built on Bokeh, so the model is inserted directly into the rendered output. Because Bokeh models are ordinarily only displayed once, some Panel functionality, such as syncing multiple views of the same model, may not work. Nonetheless this pane is very useful for combining raw Bokeh code with the higher-level Panel API.
When working in a notebook, changes to a Bokeh object may not be synced automatically and require an explicit call to pn.io.push_notebook with the Panel component containing the Bokeh object.
Parameters:#
For details on other options for customizing the component see the layout and styling how-to guides.
autodispatch(boolean, default=True): Whether to automatically dispatch events inside Bokehon_changeandon_eventcallbacks when running in the notebook.object(bokeh.models.LayoutDOM): The Bokeh model to be displayed.theme(bokeh.themes.Theme or str): The Bokeh theme to apply, either aThemeobject or the name of a built-in theme such as'dark_minimal'. See the Bokeh themes docs for details.
from math import pi
from bokeh.palettes import Category20c, Category20
from bokeh.plotting import figure
from bokeh.transform import cumsum
x = {
'United States': 157,
'United Kingdom': 93,
'Japan': 89,
'China': 63,
'Germany': 44,
'India': 42,
'Italy': 40,
'Australia': 35,
'Brazil': 32,
'France': 31,
'Taiwan': 31,
'Spain': 29
}
data = pd.Series(x).reset_index(name='value').rename(columns={'index':'country'})
data['angle'] = data['value']/data['value'].sum() * 2*pi
data['color'] = Category20c[len(x)]
p = figure(height=350, title="Pie Chart", toolbar_location=None,
tools="hover", tooltips="@country: @value", x_range=(-0.5, 1.0))
r = p.wedge(x=0, y=1, radius=0.4,
start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
line_color="white", fill_color='color', legend_field='country', source=data)
p.axis.axis_label=None
p.axis.visible=False
p.grid.grid_line_color = None
bokeh_pane = pn.pane.Bokeh(p, theme="dark_minimal")
bokeh_pane
To update a plot on a live server, we can simply modify the underlying model. In a Jupyter notebook we also have to call the pn.io.push_notebook helper function on the component or explicitly trigger an event with bokeh_pane.param.trigger('object'):
r.data_source.data['color'] = Category20[len(x)]
pn.io.push_notebook(bokeh_pane)
Alternatively the model may be replaced entirely by setting the object parameter:
from bokeh.models import Div
bokeh_pane.object = Div(text='<h2>This text replaced the pie chart</h2>')
Another benefit of using Panel to render Bokeh objects is that Bokeh callbacks work just like they would on a Bokeh server. You can therefore wrap an existing Bokeh app in Panel and it will work out of the box, both in the notebook and when served as a standalone app. In the notebook this relies on the autodispatch parameter, which is enabled by default:
from bokeh.layouts import column, row
from bokeh.models import ColumnDataSource, Slider, TextInput
# Set up data
N = 200
x = np.linspace(0, 4*np.pi, N)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))
# Set up plot
plot = figure(height=400, width=400, title="my sine wave",
tools="crosshair,pan,reset,save,wheel_zoom",
x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
# Set up widgets
text = TextInput(title="title", value='my sine wave')
offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)
# Set up callbacks
def update_title(attrname, old, new):
plot.title.text = text.value
text.on_change('value', update_title)
def update_data(attrname, old, new):
# Get the current slider values
a = amplitude.value
b = offset.value
w = phase.value
k = freq.value
# Generate the new curve
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b
source.data = dict(x=x, y=y)
for w in [offset, amplitude, phase, freq]:
w.on_change('value', update_data)
# Set up layouts and add to document
inputs = column(text, offset, amplitude, phase, freq)
bokeh_app = pn.pane.Bokeh(row(inputs, plot, width=800))
bokeh_app
Controls#
The Bokeh pane exposes a number of options which can be changed from both Python and Javascript. Try out the effect of these parameters interactively:
pn.Row(bokeh_app.controls(jslink=True), bokeh_app)
Open this notebook in Jupyterlite | Download this notebook from GitHub (right-click to download).