Share an image within a cds

Hi. I have a single image (numpy array) that I wish to display at several points on my figure. I initially tried providing the array in the image parameters along with a source CDS for the X and Y locations but it didn’t like that stating that it was expecting the image to also be in the source. So now I’ve added the image array to each row in the CDS, the key to which is now used in the image parameterisation along with X and y. This works, but it does mean I’ve increased the html filesize unnecessary through duplicating my array.

Therefore my question- is there a way I can plot images but make it share the image array for each location I want to plot it at, in order to save memory/simplify the code? I didn’t really want to have a separate file somewhere in order to use the imageURL method.

Thanks in advance for any help, may well just be me getting something wrong.

1 Like

I just want to make sure I understand, you have one single image, and you want to display that one identical image at many locations?

There are not any great options for that. All I can really think of is to make your one CDS very “wide” with different (one-element) columns that you use to drive several separate calls to image with.

source.data = dict(
    x0=[0],
    y0=[0], 
    x1=[10], 
    y1=[10], 
    ....
    image=[...],
)
p.image('x0', 'y0', ..., source=source)
p.image('x1', 'y1', ..., source=source)
...

If “several points” means ~10 points, then this is feasible, if ugly. If “several points” means ~1000 points then apart from being terribly unwieldy, Bokeh itself will slow down (this unusual usage is basically the opposite of what it is optimized for).

The only other alternative I can think of is to convert your image to a PNG that you make available at some URL and then use image_url instead.

Well, the ultimate option would be to create a custom renderer extension, basically a glyph that just dispalys your special image. But that is not a trivial undertaking.

Thanks for the answers, you are correct in terms of what I wanted to do. It’s not a major issue for me as it was only something I was playing around with and thought I’d check if I was missing something obvious. It’s around 50 or so, but it’s a small file so not too bad as is. I’d love to code up a custom extension but unfortunately each time I look at that it always seems well beyond my limited python skills. A follow up question if I may- is there a technical reason why it’s set up such that I can’t use the source only for X and Y but not for the image, as that’s the first thing I tried?

It could possibly be made to work but it would take some special casing to do so (since Image is one of the few unusual glyphs that accepts multi-dimensional inputs). But no one has ever asked for it before, so it’s never been considered.

It would probably actually be more straightforward to accommodate after Deprecate ragged array case in ImageBase.image · Issue #10090 · bokeh/bokeh · GitHub is done. For historical reasons Bokeh accepts “lists of lists” but once that is no longer the case, the special-case logic would be easier to develop and maintain. Feel free to leave a comment about this/link to this discussion on that issue if you like.