[ANN] Bokeh.jl, another plotting library!


Because there just aren’t enough plotting libraries for Julia, I made another one.

This one wraps BokehJS, which is the JavaScript component of the python Bokeh package (though it doesn’t actually call Python). It can render plots in a notebook or straight to your browser.

You can make interactive plots, add widgets and build up complex layouts. Interaction with a backing server is not implemented (yet).

TTFP is about 5 seconds on my machine, which somehow beats UnicodePlots (7 seconds).

What’s neat is that it is mostly automagically generated from the Python package, which means it supports all the same models, has all the same parameters and defaults, and has loads of documentation that I didn’t have to write.

Very much work in progress, but check out the gallery, the documentation and the repo.


Does Bokeh.jl allow binding Julia callbacks to plot widgets? And if so, would you have a MWE? Thank you.

No I’m afraid not, the only interactivity is in-browser right now. It’s planned for the future but not any time soon.

You can probably cobble something together yourself using WebIO.jl and some custom JavaScript. If you did I’d love to see it.


You mentioned that this was generated “automagically” from the Python source code. Did you use a tool, such as a transpiler, to convert it?
Thank you.

Bokeh.jl is the closest thing to MATLAB’s experience I have seen so far.
It can handle large data set while maintaining interactivity. Still not as fast as MATLAB but I haven’t seen anything else in Julia that can do this:

using Bokeh;
Bokeh.settings!(use_browser = true);
hF = figure(tooltips = [("x", "\$x"), ("y", "\$y")]); #<! The tooltips allow hovering over data to see its values
numPts = 1_000_000;
plot!(hF, Scatter, x = randn(numPts), y = randn(numPts));
display(hF); #<! Opens in a browser

Well Done!


Oh dear, I have waited so long and finally, there it is! I can now convert my Bokeh scripts to Julia. Thanks so much!


No, nothing that clever. The Python package has a script which outputs information about all the Bokeh models (the components of a plot, such as axes, glyphs, data, legends, tools, etc.). My Julia package uses a modified version of the script and then parses the resulting JSON at precompile-time to generate all the models.

The same system is used to ensure the named colours, colour palettes, and some other pieces of information are consistent with the Python version. All the other functionality is still written in Julia.


Hi! The gallery link from your post is broken, although I could easily find it maybe you would like to edit it…
Thanks for sharing!

1 Like

Thank you, I’ve fixed the link now. I recently released a new version which changed the layout of the docs.

Release: Bokeh v0.4.0 / BokehBlink v0.1.0

  • Much improved documentation (thanks to @JohnnyChen94 for helping with the gallery).
  • Plotting to browser now works in WSL.
  • New package BokehBlink provides a backend to display plots in a standalone window (docs here).
  • BokehBlink.save() can be used to generate an image of your plot.
  • Helper functions for binning data for hexagonal grids (see this example).

Is it possible to export a figure to a standalone .html file? I’ve tried the following, but it 1. asks me to confirm ingoing/outgoing connections each time, and the resulting .html files are not properly formatted.

using Bokeh, BokehBlink, Blink
# Bokeh.settings!(display=:browser) # Tried with and without

x = [1, 2, 3, 4]
y = sin.(x)

p = Bokeh.figure()
Bokeh.plot!(p, Bokeh.Line, x=x, y=y)
BokehBlink.save("testplot.html", p, format="webp")

Update: I’m sure there’s a cleaner method, but for now I accomplished this with the following:

function savebokehhtml(fname, p)
    doc = Bokeh.Document(p)
    dochtml = Bokeh.doc_standalone_html(doc)
    dochtml_split = split(dochtml, "</head>");
    dochtml_temp = String[]
    push!(dochtml_temp, dochtml_split[1])
    push!(dochtml_temp, """\n<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.1.min.js"></script>\n""")
    push!(dochtml_temp, dochtml_split[2])
    dochtml_out = join(dochtml_temp)
    open(fname, "w") do io
        write(io, dochtml_out)

Yep the latter way is the right way, but you shouldn’t need to add any extra scripts, Bokeh.doc_standalone_html(doc) should already be a self-contained document. If that’s not working for you, please post an issue on the GitHub repo.

1 Like