bokeh and Emacs org-mode
source link: http://cherian.net/posts/bokeh-org-mode.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
2. Using autoload_static
(preferred)
Based on https://necromuralist.github.io/data_science/posts/bokeh-test/
Some notes:
- This method stores the data in a separate
.js
file which should make the org file easier to handle. Also, the figure can embedded freely in many places. - Figuring where to get the bokeh css and js files can be tricky (docs):
- You can use the CDN:
from bokeh.resources import CDN
to load the bokeh js file over the internet. Not good for future-proofing. - Using
bokeh.resources.Resources(mode='absolute')
or'mode=relative'
loads bokeh from your local python installation; so that’s good for local notebooks but your figures/notebooks might break when bokeh updates. - The
inline
option inlines the necessary js and css in the exported.js
file but then with multiple images; you end up with multiple copies so that’s wasteful, but seems like the only future-proof option. Also, you can have two figures made with different bokeh versions embedded in the same document, so that’s a plus.
- You can use the CDN:
2.1. Prerequisites
I am using
- bokeh 0.12.10
- org 9.1.2
- emacs 25.3.50.2
- ob-ipython @ 1642a74
I define a function export_bokeh
to do the actual heavy lifting. This function could be moved to your ipython startup.py
file so that it is defined for every ipython session.
def export_bokeh(plot, outPNG, outJS, outHTML, bkjs='inline'): from bokeh.io import export_png from bokeh.embed import autoload_static, file_html import bokeh.resources if bkjs is 'local': # use local installed bokeh scripts wherebokeh = bokeh.resources.Resources(mode='absolute') if bkjs is 'remote' or bkjs is 'CDN': # use CDN bokeh scripts wherebokeh = bokeh.resources.CDN if bkjs is 'relative': # bkjs is a relative path to the locally installed bokeh files wherebokeh = bokeh.resources.Resources(mode='relative', root_dir='./') if bkjs is 'inline': wherebokeh = bokeh.resources.INLINE # save the png file export_png(plot, filename=outPNG) # save the html file html = file_html(plot, wherebokeh, None) with open(outHTML, 'w') as file: file.write(html) js, script = autoload_static(plot, wherebokeh, outJS) # save the .js file with open(outJS, "w") as writer: writer.write(js) # embed in the org-exported HTML file print('''#+BEGIN_EXPORT html\n{script}\n#+END_EXPORT'''.format(script=script.lstrip()))
Embedding the figure is then quite easy once you
- tell ob-ipython to capture stdout and put it in a drawer so that it’s replaced everytime to rerun the source block.
- provide a custom filename for export (
fname
below).
I use this header line:
#+BEGIN_SRC ipython :session :results output drawer :exports both :var fname="my-image" :var titlestr="Demonstrating bokeh"
2.2. Example
This will export a png image, an HTML file and a Javascript file. That way there are both static and dynamic versions that are easy to share as well as an emebeddable version.
from bokeh.plotting import figure from bokeh.layouts import gridplot from bokeh.models import ColumnDataSource, HoverTool, WheelZoomTool tools='box_select, reset' # create "subplots" p1 = figure(tools=tools) p1.background_fill_alpha = 0.0 p1.border_fill_alpha = 0.0 p2 = figure(tools=tools, x_range=p1.x_range, y_range=p1.y_range) p2.background_fill_alpha = 0.0 p2.border_fill_alpha = 0.0 # generate data x = np.random.randn(200) y0 = x**3 - 100 y1 = x**2 - 100 # generate random letters import string import random label = [random.choice(string.ascii_letters) for aa in range(200)] # needed for linked selection source = ColumnDataSource(data={'x': x, 'y0': y0, 'y1': y1, 'label': label}) # plot the data p1.circle('x', 'y0', source=source) p2.scatter('x', 'y1', source=source) p1.title.text = titlestr wheel = WheelZoomTool() # add some tooltips hover = HoverTool() hover.tooltips = [ ("(x,y)", "($x, $y)"), # '$' for co-ordinates ("label", "@label") # note '@' for column lookup ] p1.add_tools(hover, wheel) p2.add_tools(hover, wheel) p1.toolbar.active_scroll = wheel p2.toolbar.active_scroll = wheel # layout the subplots pg = gridplot([[p1, p2]], plot_width=400, plot_height=400) export_bokeh(pg, '../static/'+fname+'.png', '../static/js/'+fname+'.js', '../static/html/'+fname+'.html')
The above figure is a rendering of the RESULTS
block:
#+RESULTS: :RESULTS: #+BEGIN_EXPORT html <script src="../static/js/my-image.js" id="f1c145ed-260c-411c-8c26-f71b52427218" data-bokeh-model-id="5f0145de-1c4e-4ee2-9a64-f38f255c81ff" data-bokeh-doc-id="20261111-dbef-4dd0-b40c-d8c04db088bd" ></script> #+END_EXPORT :END:
2.3. Improvements
Things I would like:
- Automatically run the HTML export when running the code block.
- Can I add-hook to
org-babel-execute-maybe
?
- Can I add-hook to
- The ability to auto-hide the javascript in the
RESULTS
drawer but show the exported png file.- Ideally, I would see the png in the org file and the javascript in the HTML file. The other should be hidden. Seems too complicated.
- A nice solution would be to insert a link to the png file in the image caption.
- Are actual captions (
#+CAPTION
) possible with bokeh figures? - Avoid the explicit
export_bokeh
call if possible.- Ideally,
ob-ipython
would be able to tell that this is a bokeh block; use thefname
var to pass the figure handlep
andfname
toexport_bokeh
and do everything. This would be close to jupyter notebook workflow. - This might be possible using IPython formatters as suggested by the
ob-ipython
README.- Could we then define
export_bokeh
inimports.py
and call that when the returned object is a bokeh figure handle?
- Could we then define
- Ideally,
- Can we get holoviews to work with this? Optionally tell it to use either matplotlib or bokeh backends
Recommend
-
47
Bokeh prides itself on being a library for interactive data visualization. Unlike popular counterparts in the Python visualization space, like Matplotlib and Seaborn, Bokeh renders its graphics using H...
-
63
Bokeh plot gallery As a JupyterLab heavy user, I like using Bokeh for plotting because of its interactive p...
-
26
Emacs org-mode for Developers Feb. 8, 2020
-
8
The Bokeh open source Python visualization library assists developers with creating web browser visuals. You can build charts for web applications without coding any JavaScript...
-
5
Responsive Bar Charts with Bokeh, Flask and Python 3Bokeh is a powerful open source Python library that allows developers to generate JavaScript data visualizations for their web applic...
-
2
Testing Macro Diffraction and Bokeh of the Nikon Z MC 105mm f/2.8 VR S
-
3
Netops with Emacs and Org mode Vincent Bernat March 5, 2017 Also avail...
-
5
What’s this about? Spaced repetition (SR) is a type of learning technique which is predicated on a typical, observed memory degradation rate and schedules one’s reviewing intervals accordingly, so as to maximize the...
-
8
May 15, 2022Literate APIs with Emacs and Org ModeIn the last post, we looked at the Rest Client extension for VS Code. We started taking...
-
3
Task Management using Emacs and Org-mode During my daily work, I must be on top of several projects. I do the technical groundwork, plan, coordinate, and follow up with people. That is not always easy as the context switching beco...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK