Bokeh 0.12.6 Released

by Bryan Van de Ven on Tuesday, June 13, 2017

We're pleased to announce the release of Bokeh 0.12.6!

This update includes the following highlights:

  • Headless, programmatic export of SVG and PNG images
  • New annotations Whisker and Band for displaying error estimates
  • Fine-grained sub-element patching for images and other "multi" glyphs
  • Hover hit-testing extended to segments and all markers
  • Fixes for sorting and selecting from DataTables
  • Large cleanup and refactor of the layout system
  • Improved formatting options for hover tool fields and axis tick labels

Additionally, this release contains many other small bugfixes and docs additions. For full details, see the CHANGELOG and Release Notes.

As a reminder, we now package and upload examples for each Bokeh release to our CDN. Click here to download.

This release can most easily be installed from the Bokeh channel on by executing the command conda install -c bokeh bokeh if you are using Anaconda, or pip install bokeh otherwise.

SVG and PNG Export

Not surprisingly, #538—Headless static (svg, png) image generation was one of the oldest open issues on the Bokeh issue tracker. Despite enormous interest in this capability (from users and the core devs alike), technical hurdles and trade-offs prevented realizing this feature until now.

I am very happy to report that this issue has been completed! It is now possible to export static SVGs and PNGs directly from Python code thanks to the great work of Luke Canavan.

Exporting to PNG is as simple as calling one function:

export_png(plot, filename="plot.png")

This function generates a PNG image that is essentially a full screenshot of what would be rendered in the browser. Here is a PNG of the unemployment example:

It's also possible to generate SVG output, which is often requested by people wanting to use Bokeh plots in scientific publications:

plot.output_backend = "svg"
export_svgs(plot, filename="plot.svg")

Do note the plural in the function name. When exporting grid plots or layouts with multiple plots, export_svgs will generate a separate SVG for every plot: plot.svg, plot_1.svg, plot_2.svg, etc. This is different from the "full screenshot" style of the PNG export, but should be useful for those embedding plots into publications who want finer control of what-goes-where. Here is an SVG of the same unemployment example above:

To use this new capability, some additional optional dependencies (such as Selenium) must first be installed. See the new User's Guide section Exporting Plots for information about how to get everything up and running. Like all new features, there will almost certainly be some kinks to straighten out. Please report any issues (with full details) on the issue tracker.

Layout System Improvements

Bokeh 0.12 introduced a new layout system for entire documents, affording the ability to display sophisticated data applications with multiple controls and plots. However, the layout system is complex, and more than a few problems have turned up since it was added. Thanks to the tireless work of Mateusz Paprocki, this release saw a major cleanup of the entire layout system. In general, the responsiveness of layout has been improved, but most importantly many bugs were fixed:

#4764—Issue with interactions between widgets and plots using bokeh server

#4810—Trouble Swapping out layout contents when using server

#5131—Unexpected initial layout with DataTable and layout()

#5518—Add new child to existing column

#5879—Make "bokeh finished rendering heuristic" work with non-plot examples

#6213—Appending layout regression

Additionally, a lot of behind the scenes refactoring puts the Bokeh layout capability on solid footing for the future.

Bands and Whiskers

Another long-requested feature is annotations for reporting errors and uncertainty. The plot below shows off the new Whisker and Band annotations:

Future planned improvements include an errorbar function to help make using these annotations even easier.

For good measure, this plot also shows off some new syntax that makes overriding tick formatting a snap. The x-coordinates in the plot number successive trading days. We want to label every fifth value (i.e. every Monday) as a new week, which can now be done easily like this:

p.xaxis.ticker = mondays # [0, 5, 10, ...]
p.xaxis.major_label_overrides = { d: "week %d" % i for i, d in enumerate(mondays)}

Efficient Streaming for Higher Dimensional Data

Bokeh has had patch and stream methods on ColumnDataSource for some time now. These allow for efficient or incremental updates to individual items in CDS columns. For most cases, where the columns are one-dimensional arrays, this is a great benefit. But for some glyphs, such as MultiLine and Image, the items in the columns are themselves arrays. In these cases, patch was not nearly as useful as it could be—until now. Now it is possible to use patch to partially update individual locations or slices of CDS column items that are arrays. The demo below shows patch being used to update subsets of circles, multi-lines, and images all at once:

You can find more information in the Reference Guide or check out and run the source code for the above example at examples/howto/

High-level Charts

Looking towards a 1.0 release, we are in the process of paring down Bokeh for long term stability and maintenance. We want to make it a rock solid platform for other high level and domain specific tools to build on. As part of this, we have decided to cleave bokeh.charts from the core library.

bokeh.charts is now a separate package.

The new project is called bkcharts. Current usage of bokeh.charts will work (with a deprecation warning) until Bokeh 1.0 is released. At that time, it will be be necessary to separately install and import from the bkcharts package to continue using this API. However, due to resource constraints, support and maintenance for bkcharts by the current team will be extremely minimal from this point on .

Accordingly, I would instead encourage everyone looking for very high level charting with Bokeh to look in a new (and much better) direction: HoloViews is a separately maintained package that provides a concise declarative interface for building Bokeh plots. It is actively maintained by Jean-Luc Stevens, Philipp Rudiger, and Jim Bednar. HoloViews is particularly focused on interactive use in a Jupyter notebook, allowing quick prototyping of figures for data analysis. Click on any of the thumbnails below to see concrete usage of HoloViews' very high level, data-oriented API:

In addition to close integration with Bokeh, Holoviews can also coordinate the Datashader library for dealing with large (billion+ point) data sets. Together, these three projects bring together the vision for "high-level data applications for large and streaming data in the browser" that Peter Wang and I set out to create four years ago. Expect much more information, demonstration, and documentation about using these tools seamlessly together in the coming weeks. In particular, there will be a tutorial at SciPy 2017 in July (available afterward on YouTube).

Next Steps

As stated above, there aren't a lot of big-ticket features left to put in to Bokeh before we are ready to cut a 1.0 release. Here is a rough outline (subject to change) of the work we plan to do over the next few months:

  • Network/Graph data source and renderers
  • Improved binary transport for array data
  • Scriptable animations and transitions
  • Improvements to Categoricals (e.g. nested axes)
  • New events for document init, busy/done, etc.
  • Complete migration to TypeScript
  • Publish BokehJS reference documentation
  • Support "Patches with holes" for GIS usage
  • Integrate with VegaLite/Altair
  • Remove all existing deprecations
  • Cleanup: bugfixes, docs, automation, polish

As we're getting closer to a Bokeh 1.0 release, I'd like to thank the 231 total contributors who have helped make Bokeh such an amazing project. As always, for technical questions or assistance, or if you're interested in helping out, please post to the Bokeh mailing list or join the chat on Gitter.


Bryan Van de Ven