How to refresh figure in Bokeh?

I have the following code in Bokeh. It displays four dots in red. The user can select another color from the dropdown, click ‘Run’ and the dots are to change color. With this code, the dots do not change color nor does the image_1.png get updated. Any advise on how I could refresh image_1.png and display it correctly? Thanks indeed!

from bokeh.layouts import column, row
from bokeh.models import (Select, Button)

from bokeh.plotting import curdoc, figure

from bokeh.layouts import column, layout
import numpy as np 
import matplotlib.pyplot as plt


x_range=(0,100)
y_range=(0,100)

color_1 = ['red','blue','yellow']
N = 4
x = np.random.random(size=N) * 10
y = np.random.random(size=N) * 10
radii = 15#np.random.random(size=N) * 15

line_color = Select(value='red',
                        title='color:',
                        width=200,
                        options=color_1)

p = figure(tools="reset,pan,wheel_zoom,lasso_select")

file_name_1 = "test_sp/static/image_1.png"

def button_callback():
    print('bc')
    p = figure(tools="reset,pan,wheel_zoom,lasso_select")
    layout.children[1] = create_figure()
    return p




def create_figure():
    c1 = line_color.value
    print(c1)
    file_name_1 = "test_sp/static/image_1.png"
    plt.scatter(x,y,radii,color=c1,alpha=0.6)
    
    plt.savefig(file_name_1)
    p = figure(tools="reset,pan,wheel_zoom,lasso_select")
    p.image_url(url=[file_name_1],x=x_range[0],y=y_range[1],w=x_range[1]-x_range[0],h=y_range[1]-y_range[0])
    return p
  

    
button = Button(label='Run', width=100, button_type="success")



button.on_click(button_callback)


selects = column(line_color,button, width=420)
layout=row(selects, create_figure())

curdoc().add_root(layout)

curdoc().title = "color the dots"

The code I posted here is the complete minimal example of a much larger code where I update the Bokeh figure (based on user inputs from the front-end, save it and then refresh the front-end). This is why I have a ‘run’ button in the front-end (to collect the user inputs) and a create figure() in the Bokeh code to allow me to construct a Bokeh figure (which is a .png saved from a matplotlib plot). I still need the ‘run’ button and create_figure(). My issue is that even though the .png gets updated on the server side, I am unable to refresh the front end with this updated .png. Any advise on how to refresh the Bokeh figure…?

(I have also posted this question on stackoverflow: button - How to refresh figure in Bokeh? - Stack Overflow)

@sandhya212 It’s possible your browser cache is interfering. I would suggest looking into the browser dev tools. There may be useful messages in the JS console log, and there maybe be relevant information in the network tab as well.

Thank you @Bryan for the answer. I am very new to server-side development. Please let me know what I should look for in the browser dev tools/JS console log. Also what is the network tab - is this the terminal?

@sandhya212 These are all browser tools, and they differ by browser, so I can’t give you specific instructions. You’ll need to look up how to access them on whatever platform/browser you are actually using. Here is a screen shot with the dev tools in Safari opened up:

You can see the network tab shows all scripts, resources, etc that were attempted to be loaded, status result, and whether or not they were cached, etc. The console tab is also there and I would say look for anything that looks like an error message. Generally there should not be error messages in the log.

Lastly would only mention that it’s often necessary to open up the dev tools on a page, then reload the page, e.g to get the network tab to actually show results.

Thank you again @bryan. I use Chrome and have checked the console log as you suggested. I notice two errors (pasted here). Do you think these are responsible for the images not getting refreshed? I do not know what these mean but will do some research to figure this out. Will update if I find something. Thanks again!

DevTools failed to load SourceMap: Could not load content for http://localhost:5094/static/js/bokeh.min.js.map: HTTP error: status code 404, net::ERR_HTTP_RESPONSE_CODE_FAILURE

[Violation] Added non-passive event listener to a scroll-blocking ‘wheel’ event. Consider marking event handler as ‘passive’ to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952```

Neither of those is important or relevant. You should look in the network tab and try to watch what happens with image_1.png. You could also experiment with making sure to give different new filenames each time just to see if that affects things.

Each time image_1.png had to be rendered, I got this same
[Violation] Added non-passive event listener to a scroll-blocking ‘wheel’ event. Consider marking event handler as ‘passive’ to make the page more responsive.

I tried a new filename (a random number instead of ‘1’ in image_1.png) and indeed, this worked! Yayyy! Thank you :+1:

If a filename is created with a previously-generated random number, then the older image gets thrown to the screen. So does this indicate that the browser cache was interfering with a page refresh? Could I clean the cache through the Bokeh code?

Thanks again!

Seems like it.

Could I clean the cache through the Bokeh code?

I don’t think so. If the images were coming from a proper web server, then you could try cache-busting by adding some junk URL arguments to the end of the URL. Or you could configure the web server to respond with headers that prevent caching. Otherwise how browsers handle caching (and especially for local filesystem paths) is 100% outside of anything we can control.

For what it’s worth, ImageURL was really intended to be used with real HTTP(s) locations, not local filesystem paths. BTW please do be aware (if you are not already) that what you are doing now will not work at all for remote viewers. Their browser will try to load the file from their local filesystem (because that’s what the “URL” says to do), and of course will not work. If you need to support remote viewers of the app, you will have to find a way to host the images at real web URLs (or else convert the image to an array and use ImageRBGA instead).

Thank you again, Bryan for the insights.

I did not know this aspect of ImageURL. The project I am developing will allow users to use their own data (I can instruct them on how to organise the files structure) so that image_x.png will get generated, saved and rendered from the user’s local machine. Also, for remote viewing (such as a demo, I think), I shall upload a few images to a web URL.