Critics and ideas on my datashader usage in pure bokeh

Hello,

I’m writing a dashboard using mostly bokeh, on a tornado server (to do Wamp communications via crossbar.io’s autobahn library for python, btw: a great combination).

First off, i know that the use of holoviews for datashader is encouraged and i’ve considered it but i still choose to go with bokeh only.

My current approach is simple : every time i detect a change on x_range or y_range, i launch my little routine to create a new rasterized view. Here is the “simplified” code of what i do:

async def display_raster(graph, data): #graph is my class with plot inside
        N = 500
        df = pd.DataFrame({"x": data.x, "y": data.y})

        x_s = graph.p.x_range.start
        y_s = graph.p.y_range.start
        x_e = graph.p.x_range.end
        y_e = graph.p.y_range.end
        width = x_e - x_s
        height = y_e - y_s

        canvas = ds.Canvas(
            plot_width=N,
            plot_height=N,
            x_range=([x_s, x_e]),
            y_range=([y_s, y_e]),
            x_axis_type=graph.config["x_axis_type"],
            y_axis_type=graph.config["y_axis_type"],
        )

        agg = canvas.points(df.where(df >= 0), "x", "y", agg=ds.count())
        shade = np.array(tf.shade(agg, cmap=bmy))

        prev_raster = graph.p.select(name="raster")


        plot.image_rgba(image=[shade], x=x_s, y=y_s, dw=width, dh=height, name="raster")

        for r in prev_raster:
            graph.p.renderers.remove(r)

[…] (somewhere else)

            call_raster_update = lambda a, o, n: graph.doc.add_next_tick_callback(
            partial(range_change_callback, a, o, n))

            graph.p.x_range.on_change("end", call_raster_update)
            graph.p.y_range.on_change("end", call_raster_update)
            await display_raster(graph, plotable)

This is working-ish, the first rasterization takes ~ 1sec and the next ones ~0.1s. Problem is : I don’t find this very elegant and i do get rasterizations pilling up if i zoom/pan a lot. Any thought and ideas on how to make it better ? Thanks for reading and thanks a lot to bokeh/datashader contributors for the awesome tool :wink:

@Cyclopede

Depending on your user interaction requirements, you might consider replacing on_change() callbacks with on_event() callbacks.

For example, registering the existing logic to trigger on PanEnd would invoke the updates when you’re done panning/zooming rather than many times as the user interactively manipulates the plot ranges. (And perhaps also register the callback on LODEnd events if you need the user to do other things.)

You can look at https://github.com/holoviz/datashader/blob/master/datashader/bokeh_ext.py#L132 for an example of a pure-Bokeh workflow for Datashader, but we abandoned that approach as being too limited to be useful, so take that as you may. The problem with using Datashader in pure Bokeh is just that you spend a lot of time optimizing one particular application, and then can’t easily transfer that work to other applications because the callback structure gets very specific. That’s why we only support the HoloViews approach nowadays, as that can be compositional and reusable.