Styling and theming¶
Bokeh can be used to configure various visual aspects of the diagrams.
Firstly, we make the standard imports:
[1]:
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
[2]:
output_notebook()
Colours¶
Bokeh can take on colours in different ways:
one of the 147 named CSS colours, for example
green
,indigo
an RGB(A) hexadecimal value, for example
#FF0000
,#44444444
a 3-tuple of integers
(r,g,b)
between 0 and 255a 4-tuple of
(r,g,b,a)
wherer
,g
andb
are integers between 0 and 255 anda
is a floating point value between 0 and 1
Properties¶
Regardless of how a bokeh plot is created, the design can always be defined by attributes for the bokeh objects that make up the resulting plot. There are three types of visual properties: line
, fill
and text
properties. Complete information with code and examples can be found in the Styling Visual Properties section of the user manual.
Plots¶
Many top-level attributes of plots (outline
, border
etc.) can be configured. Detailed information can be found in the Plots section.
Here is an example that describes the plot frame:
[3]:
p = figure(width=400, height=400)
p.border_fill_color = "whitesmoke"
p.min_border_left = 30
p.circle([1,2,3,4,5], [2,5,8,2,7], size=10)
show(p)
Glyphs¶
It is also possible to design the visual properties of glyphs. If you use bokeh.plotting
, this is often done when calling the glyph methods:
p.circle (line_color = "red", fill_alpha = 0,2, ...)
However, it is also possible to specify these properties directly on glyph objects. Glyph objects are found in GlyphRenderer
objects that are returned by the Plot.add_glyph
and bokeh.plotting
methods. Let’s take a look at an example:
[4]:
p = figure(width=400, height=400)
# keep a reference to the returned GlyphRenderer
r = p.circle([1,2,3,4,5], [2,5,8,2,7])
r.glyph.size = 50
r.glyph.fill_alpha = 0.2
r.glyph.line_color = "firebrick"
r.glyph.line_dash = [5, 1]
r.glyph.line_width = 2
show(p)
selection
and nonselection
visuals¶
You can also specify how the glyphs should look. The set of selected points is designed according to the optional .selection_glyph
property of a GlyphRenderer
:
r.selection_glyph = Circle(fill_alpha=1, fill_color="firebrick", line_color=None)
The non-selected points can be designed with the optional .nonselection_glyph
property of a GlyphRenderer
:
r.nonselection_glyph = Circle(fill_alpha=0.2, fill_color="grey", line_color=None)
If you use the bokeh.plotting
interface, you can pass these visual properties to the glyph methods more easily (see below). The glyph method creates the selection
or non-selection
glyphs and attaches them to the renderer.
[5]:
p = figure(width=400, height=400, tools="tap", title="Select a circle")
renderer = p.circle(
[1, 2, 3, 4, 5],
[2, 5, 8, 2, 7],
size=50,
# set visual properties for selected glyphs
selection_color="firebrick",
# set visual properties for non-selected glyphs
nonselection_fill_alpha=0.2,
nonselection_fill_color="grey",
nonselection_line_color="firebrick",
nonselection_line_alpha=1.0,
)
show(p)
It is also possible to specify the visual appearance of glyphs, for example by setting the optional hover_glyph
:
r.hover_glyph = Circle(fill_alpha=1, fill_color="firebrick", line_color=None)
Or if bokeh.plotting
glyph methods are used by passing hover_fill_alpha
etc. to the glyph method. Let’s look at an example configured with a HoverTool
for hline
:
[6]:
from bokeh.models.tools import HoverTool
from bokeh.sampledata.glucose import data
subset = data.loc["2010-10-06"]
x, y = subset.index.to_series(), subset["glucose"]
# Basic plot setup
p = figure(
width=600, height=300, x_axis_type="datetime", title="Hover over points"
)
p.line(x, y, line_dash="4 4", line_width=1, color="gray")
cr = p.circle(
x,
y,
size=20,
fill_color="grey",
hover_fill_color="firebrick",
fill_alpha=0.05,
hover_alpha=0.3,
line_color=None,
hover_line_color="white",
)
p.add_tools(HoverTool(tooltips=None, renderers=[cr], mode="hline"))
show(p)
Axes¶
Next, we look at the styling of axes.
To style axes, axis objects must first be created. The easiest way is to use some convenient methods for Plot
: axis, xaxis and yaxis. These methods return a list of axis objects:
>>> p.xaxis
[<bokeh.models.axes.LinearAxis at 0x106fa2390>]
However, you can set properties for all elements of the list, for example:
p.xaxis.axis_label = "Temperature"
p.axis.major_label_text_color = "orange"
Tab completion also works: For example, enter p.xaxis
. in a notebook cell and then press the tab key to see a list of attributes that can be set here:
Axis properties¶
Axis objects have many configurable properties that can be used to control most visual aspects of an axis. These can be grouped by function with a prefix:
Line Properties, for example * axis_line_width
* major_tick_line_dash
, major_tick_in and major_tick_out
* minor_tick_line_width
, minor_tick_in and minor_tick_out
Text Properties, for example * axis_label
, axis_label_text_color
, axis_label_standoff
* major_label
, major_label_text_font_size
, major_label_orientation
As a simple first case, we change the orientation of the main auxiliary labels on both axes of a drawing:
[7]:
from math import pi
p = figure(width=400, height=400)
p.x([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10, line_width=2)
p.xaxis.major_label_orientation = pi / 4
p.yaxis.major_label_orientation = "vertical"
show(p)
The next example shows adjustments to several of the different axis properties at the same time:
[8]:
p = figure(width=400, height=400)
p.asterisk([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=12, color="olive")
# change just some things about the x-axes
p.xaxis.axis_label = "Temp"
p.xaxis.axis_line_width = 3
p.xaxis.axis_line_color = "red"
# change just some things about the y-axes
p.yaxis.axis_label = "Pressure"
p.yaxis.major_label_text_color = "orange"
p.yaxis.major_label_orientation = "vertical"
# change things on all axes
p.axis.minor_tick_in = -3
p.axis.minor_tick_out = 6
show(p)
Configuring markers¶
All Bokeh axes have a formatting property whose value is a TickFormatter
object that Bokeh uses to format the tick marks displayed by that axis. Bokeh configures default tick marks for numeric, date or categorical axes. However, we often want to customise the appearance of marker labels. This can be achieved by changing the properties of the default formatter selected by Bokeh or by completely replacing the formatter with a new type.
Firstly, we will now change the properties of a default formatter. The default date format is configured to display month/day when the axis is on the scale of days. If you want the year to always be displayed as well, you can change the Days property to a format that includes the year (see below).
[9]:
from math import pi
from bokeh.sampledata.glucose import data
week = data.loc["2010-10-01":"2010-10-08"]
p = figure(
x_axis_type="datetime", title="Glocose Range", height=350, width=800
)
p.xaxis[0].formatter.days = "%d.%m.%Y"
p.xaxis.major_label_orientation = pi / 3
p.line(week.index, week.glucose)
show(p)
Further information that can be updated can be found in the DatetimeTickFormatter reference manual.
In addition to the tick formatters that Bokeh uses by default, there are others such as the NumeralTickFormatter
that are explicitly configured. The following example shows how you can set a formatter for each axis:
[10]:
from bokeh.models import NumeralTickFormatter
p = figure(height=300, width=800)
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
p.xaxis.formatter = NumeralTickFormatter(format="0.0%")
p.yaxis.formatter = NumeralTickFormatter(format="$0.00")
show(p)
There are many other ways to control tick label formatting, including the ability to provide a JavaScript snippet for arbitrary formatting in the browser. Further information can be found in Tick Label Formats.
It is also possible to specify where the tick marks are drawn. Further information can be found in the Tick Locations section of the user manual.
Grids¶
It is also possible to control the design of grids.
Grid properties in Bokeh have two possible prefixes:
grid
properties (thus line properties) control the grid linesband
properties (thus fill properties) control the stripes between the grid lines
In the first example, we deactivate the vertical grid lines (by setting the line colour to None
) and make the horizontal grid light and dashed.
[11]:
p = figure(width=400, height=400)
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
# change just some things about the x-grid
p.xgrid.grid_line_color = None
# change just some things about the y-grid
p.ygrid.grid_line_alpha = 0.5
p.ygrid.grid_line_dash = [6, 4]
show(p)
The next example shows how the band
properties of a diagram can be specified:
[12]:
p = figure(width=400, height=400)
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
# change just some things about the x-grid
p.xgrid.grid_line_color = None
# change just some things about the y-grid
p.ygrid.band_fill_alpha = 0.05
p.ygrid.band_fill_color = "olive"
show(p)