I've been playing with bokeh for a little bit of time and I'm now at the step where I'd like to create interactive plots and embed them online (in WordPress posts, for example).
However, even though I spent some time reviewing and testing code from the bokeh website examples, I have a hard time understanding exactly what is the purpose of curdoc(). It seems to be necessary in order to create a bokeh app with widgets, but from what I found in the ressources, I don't quite understand it.
Some terminology is in order. When you create a Bokeh plot, it is comprised of lots of smaller objects, for instance glyphs, ranges, data sources, tools, etc. And the plot itself, is basically a container for all these other objects. All these objects, including the Plot, are called Models. Other Models are things like layouts (e.g. row
and column
) as well as the widgets built-in to Bokeh (e.g., Slider
or Select
).
For every one of these models on the Python side, there is a corresponding JavaScript object that actually implements the model, and does all the work in the browser for drawing or interaction. The way Bokeh works is it can automatically turn a collection of Python models into a pile of JSON, and then BokehJS can re-constitute all the corresponding JS objects from that.
A Document is a collection of Bokeh Models. It is the smallest "unit of serialization". That is, it often doesn't make sense to turn a single Python model into JSON (like a Plot
) because the object might refer to lots of other objects (like axes, or glyphs, etc.) So, a collection of models in a Bokeh Document can all be turned into JSON, together, in a meaningful way.
All of the above applies whether you are making standalone documents (e.g. with output_file
), or creating Bokeh applications on a Bokeh server. In the case of Bokeh applications, the application code itself is really just a recipe for modifying a document. So whenever a Bokeh app session is created (i.e. whenever a user opens a URL to a bokeh app on a Bokeh server), a new blank Document
is created for it, and the app code is run, where the new Document
for that session is available as curdoc()
. Then the app code can add things to this document (e.g. with curdoc().add_root(...)
and as soon as the app code is finished, the "completed" document is what gets turned to JSON and sent to BokehJS to show to the user.
The last bit to mention is that the main purpose of the Bokeh server is to makes sure that Bokeh documents created this way stay in sync with the user's view in the browser, automatically. If a user scrubs a slider, that updates a Slider
model in the JS document in the browser, which automatically updates the python Slider object in the Python Document in the Bokeh server as well. The application can respond to this, and make other changes (maybe updating a Python data source say), which causes the JS data source to also update (and thus makes the plot change). This automatic two-way synchronization is what affords all the sophisticated interactive capabilities with a Bokeh server.