1

I'm trying to update a Bokeh plot in Django when new data is received via a websocket implemented with Django Channels. The aim is to stream new data received over the websocket without having to refresh the browser.

My django view creating the bokeh plot is:

#in views.py
def sensor(request):
    plot = figure(title= 'title' ,
        x_axis_label= 'X-Axis',
        y_axis_label= 'Y-Axis',
        plot_width =900,
        plot_height =500

    source = ColumnDataSource(data=dict(x=[], y=[]))
    plot.line('x', 'y', source=source, legend= 'f(x)', line_width = 2)

    script, div = components(plot)

    return render(request,"sensor.html",{'div':div,'script':script})

The JQuery associated with the websocket is the following (I receive the message as JSON formatted text):

//In a script tag in sensor.html
$(function() {
  var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
  var endpoint = ws_scheme + '://' + window.location.host + window.location.pathname
  var ws = new WebSocket(endpoint);

  ws.onopen = function(e) {
         console.log("open", e);
  };

  ws.onmessage = function(e) {
      console.log("message", e);
      var new_data = jQuery.parseJSON(e.data).data);

      // UPDATE BOKEH ColumnDataSource WITH new_data 

  };
});

My problem is that I have no idea how to update the Bokeh ColumnDataSource via JQuery. The closest I've found is using Bokeh CustomJS Callbacks, but I don't see any way of connecting them with the websocket onmessage event, and accessing data collected via the event.

Another option I've tried is embedding a separate Bokeh Server, but I can't find a way to update the plots using my Django Channels websockets. I would also have to pass data from my Django models to the Bokeh server when initializing the plots, which is inconvenient.

And assistance/advice would be appreciated. Thank you

1 Answer 1

2

You are nearly the first person to suggest or ask about this [1], to my knowledge. I am afraid there is not currently a good answer for you. The Bokeh protocol is well-defined and isolated, so in principle it can be used to communicate over any suitable channel, but currently the only things that make use of it are:

  • The standard default Tornado-based Bokeh server, which creates and manages its own websocket connections

  • Jupyter extensions, which use Jupyter comms to send the messages.

To use Django channels would mean re-implementing some subset (or all) of the current Tornado Bokeh server on top of Django. It might also necessitate changes to BokehJS itself. In any case this is definitely in the realm of nontrivial, i.e. I'd estimate at the very least a few weeks work for someone who already had alot of experience with Bokeh internals.

I'd be happy to try and discuss more details, specifically as they relate to your use case. It's possible that you have simplifying assumptions that might make alternative options possible (e.g. if you only ever need to push data to bokeh plots, and don't need the two-way sync that the Bokeh server affords, then you could probably conjure your own simple protocol). But that kind of iterative discussion is better for the public mailing list than SO.

[1] A commercial client recently also asked about Channels, and may even pursue funded work to add this capability, but I have no way to speculate when or if that would actually happen.

Sign up to request clarification or add additional context in comments.

1 Comment

That helps. Thanks. We need data streaming via websockets but given the difficulty in implementing this with Bokeh, perhaps it is better moving to a jquery plugin for visualization like Chart.js or Google Charts before we invest more time in Bokeh visualizations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.