As Bokeh moves towards a 1.0 version, the number of features and shortcuts that users can use to build rich apps and dashboards increases with every new release. Some of the hot questions recently being asked are:
- Do I need bokeh server to build a dashboard?
- Is it ready for production?
- I have a large custom dataset, can I use Bokeh to visualize my data?
Well, as in most cases the answer is YES .. and NO! Those are very generic questions (more or less like when someone asks “is Python a good programming language?”) and the right answer is different in every single specific case. Although valid, the previous questions are not really useful without the needs, the context, and a solid understanding of the technology being discussed.
So my advice before starting is:
- understand the user requirements (expressed in features and performance), the system specifications, constraints, deadlines, etc..
- collect information about the Bokeh project, read its documentation, try the examples, etc…
With that in mind, the intention of the this blog post is to show a combination of some of the recent additions to Bokeh that are probably less known then the bokeh-server but can be a very helpful alternative to create custom rich interactive dashboards.
For this post we are going to be looking at the Stocks Resampling Demo from the bokeh-demos repository, where you can download the code and try it yourself. To summarize, the demo implements a dashboard that shows stocks prices over the years and supports a downsampling logic to recreate the main plot when an user selects a region on the upper selection plot.
Instead of explaining line by line I’ll talk about the main Bokeh objects acting together in this demo and how they are being used.
CustomJS (previously known as Callback)
- a web service to serve your plot data (in our demo we are using a flask app)
To see how those ingredients can be used to build a dashboard take a look at the custom_stocks_panel.py file that can be found at the repo mentioned earlier.
Here’s a brief explanation of each of those ingredients and how they work together on that example:
1. Plotting API
Bokeh plotting API is the “mid level” interface that can be used to create plots and widgets on your page. It has been part of the library for quite a while and probably is the ingredient of our demo that needs less presentation. But before going ahead there is one aspect that is good to remark and that is useful to understand: every glyph draw on a plot figure created by the plotting API is connected to a “data source”, usually a ColumnDataSource. I encourage the reader to look at the documentation for a better understanding of what a ColumnDataSource is but to simplify let’s consider it as just a bag of data that the figure renderers use to retrieve the data they need to create the glyphs when drawing the figure on the browser.
create_selection_plot are 2 examples of of the plotting API in action.
While the name may sound fancy or complicated for this different type of data source, it’s not. Trying to keep things simple, if we defined a ColumnDataSource as “just a bag of data” we can simplify the explanation of the AjaxDataSource by saying that it’s like a ColumnDataSource but instead of keeping this bag of data locally it keeps being synchronized with a remote service that returns the data when asked.
In the demo the data source is defined as:
It means that Bokeh is going to send a get request to ‘http://localhost:5000/data’ every second to get updated data (if there’s any). It’s a simple code change but very powerful!
CustomJS (formerly called
components is not really mandatory and we could have just used Bokeh layout objects such as HBox and VBox but at the moment using
components give us a much higher level of style customization and application extendability. What it does is to return the individual Bokeh components for a inline embedding in your own web page. The components() function takes either a single PlotObject, a list/tuple of PlotObjects, or a dictionary of keys and PlotObjects. Each returns a corresponding data structure of script and div pairs (please refer to the related documentation section for more details).
It’s possible to see it being used on the demo
newapplet view function to retrieve the components and pass them to a custom template named “stocks_custom.html” that can be found inside the templates folder.
It’s also worth mentioning that it’s possible to use this feature to create customized styles. In the case of the demo a shared style variable is being used by the python code to style the bokeh objects (see the
style_axis function) and by the main view serving the page to select the specific theme css file (see the template file at templates/stocks_custom.html)
EXTRA. Using a custom flask server
If you have an external web service that you can communicate with to control your data and your app behaviour then you can actually achieve very powerful functionalities. In the specific case of this demo the custom flask service is the final component that interacts with the previous Bokeh features listed before to provide a live downsampling functionality.
The flask server code implemented by the flask_server_minutes.py file that can be found in the bokeh-demos repository mentioned above. The interesting parts are the views that are used by the AjaxDataSource to retrieve the data (see view function
get_data) and the views exposed to ask the server to resample the data on a different selected interval (see the view function
The demo that we have been considering in this post is an example of how different components of bokeh can be put together to build a rich featured customized dashboard without much code.
We hope you find this post useful.