☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Critics and ideas on my datashader usage in pure bokeh

Community Support
Cyclopede
Cyclopede

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:

⌁   Link to post
_jm
_jm

@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.)

⌁   Link to post
James_A_Bednar1
James_A_Bednar1

You can look at datashader/bokeh_ext.py at master · holoviz/datashader · GitHub 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.

⌁   Link to post

End of archived discussion · Replies are disabled